home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / mfc / src / olemisc.cpp < prev    next >
C/C++ Source or Header  |  1998-06-16  |  40KB  |  1,360 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12.  
  13. #ifdef AFX_OLE_SEG
  14. #pragma code_seg(AFX_OLE_SEG)
  15. #endif
  16.  
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21.  
  22. #define new DEBUG_NEW
  23.  
  24. /////////////////////////////////////////////////////////////////////////////
  25. // Debug diagnostics for SCODEs
  26.  
  27. #ifdef _DEBUG
  28. LPCTSTR AFXAPI AfxGetScodeString(SCODE sc)
  29. {
  30.     struct SCODE_ENTRY
  31.     {
  32.         SCODE sc;
  33.         LPCTSTR lpszName;
  34.     };
  35.     #define MAKE_SCODE_ENTRY(sc)    { sc, _T(#sc) }
  36.     static const SCODE_ENTRY scNameTable[] =
  37.     {
  38.         MAKE_SCODE_ENTRY(S_OK),
  39.         MAKE_SCODE_ENTRY(S_FALSE),
  40.  
  41.         MAKE_SCODE_ENTRY(CACHE_S_FORMATETC_NOTSUPPORTED),
  42.         MAKE_SCODE_ENTRY(CACHE_S_SAMECACHE),
  43.         MAKE_SCODE_ENTRY(CACHE_S_SOMECACHES_NOTUPDATED),
  44.         MAKE_SCODE_ENTRY(CONVERT10_S_NO_PRESENTATION),
  45.         MAKE_SCODE_ENTRY(DATA_S_SAMEFORMATETC),
  46.         MAKE_SCODE_ENTRY(DRAGDROP_S_CANCEL),
  47.         MAKE_SCODE_ENTRY(DRAGDROP_S_DROP),
  48.         MAKE_SCODE_ENTRY(DRAGDROP_S_USEDEFAULTCURSORS),
  49.         MAKE_SCODE_ENTRY(INPLACE_S_TRUNCATED),
  50.         MAKE_SCODE_ENTRY(MK_S_HIM),
  51.         MAKE_SCODE_ENTRY(MK_S_ME),
  52.         MAKE_SCODE_ENTRY(MK_S_MONIKERALREADYREGISTERED),
  53.         MAKE_SCODE_ENTRY(MK_S_REDUCED_TO_SELF),
  54.         MAKE_SCODE_ENTRY(MK_S_US),
  55.         MAKE_SCODE_ENTRY(OLE_S_MAC_CLIPFORMAT),
  56.         MAKE_SCODE_ENTRY(OLE_S_STATIC),
  57.         MAKE_SCODE_ENTRY(OLE_S_USEREG),
  58.         MAKE_SCODE_ENTRY(OLEOBJ_S_CANNOT_DOVERB_NOW),
  59.         MAKE_SCODE_ENTRY(OLEOBJ_S_INVALIDHWND),
  60.         MAKE_SCODE_ENTRY(OLEOBJ_S_INVALIDVERB),
  61.         MAKE_SCODE_ENTRY(OLEOBJ_S_LAST),
  62.         MAKE_SCODE_ENTRY(STG_S_CONVERTED),
  63.         MAKE_SCODE_ENTRY(VIEW_S_ALREADY_FROZEN),
  64.  
  65.         MAKE_SCODE_ENTRY(E_UNEXPECTED),
  66.         MAKE_SCODE_ENTRY(E_NOTIMPL),
  67.         MAKE_SCODE_ENTRY(E_OUTOFMEMORY),
  68.         MAKE_SCODE_ENTRY(E_INVALIDARG),
  69.         MAKE_SCODE_ENTRY(E_NOINTERFACE),
  70.         MAKE_SCODE_ENTRY(E_POINTER),
  71.         MAKE_SCODE_ENTRY(E_HANDLE),
  72.         MAKE_SCODE_ENTRY(E_ABORT),
  73.         MAKE_SCODE_ENTRY(E_FAIL),
  74.         MAKE_SCODE_ENTRY(E_ACCESSDENIED),
  75.  
  76.         MAKE_SCODE_ENTRY(CACHE_E_NOCACHE_UPDATED),
  77.         MAKE_SCODE_ENTRY(CLASS_E_CLASSNOTAVAILABLE),
  78.         MAKE_SCODE_ENTRY(CLASS_E_NOAGGREGATION),
  79.         MAKE_SCODE_ENTRY(CLIPBRD_E_BAD_DATA),
  80.         MAKE_SCODE_ENTRY(CLIPBRD_E_CANT_CLOSE),
  81.         MAKE_SCODE_ENTRY(CLIPBRD_E_CANT_EMPTY),
  82.         MAKE_SCODE_ENTRY(CLIPBRD_E_CANT_OPEN),
  83.         MAKE_SCODE_ENTRY(CLIPBRD_E_CANT_SET),
  84.         MAKE_SCODE_ENTRY(CO_E_ALREADYINITIALIZED),
  85.         MAKE_SCODE_ENTRY(CO_E_APPDIDNTREG),
  86.         MAKE_SCODE_ENTRY(CO_E_APPNOTFOUND),
  87.         MAKE_SCODE_ENTRY(CO_E_APPSINGLEUSE),
  88.         MAKE_SCODE_ENTRY(CO_E_BAD_PATH),
  89.         MAKE_SCODE_ENTRY(CO_E_CANTDETERMINECLASS),
  90.         MAKE_SCODE_ENTRY(CO_E_CLASS_CREATE_FAILED),
  91.         MAKE_SCODE_ENTRY(CO_E_CLASSSTRING),
  92.         MAKE_SCODE_ENTRY(CO_E_DLLNOTFOUND),
  93.         MAKE_SCODE_ENTRY(CO_E_ERRORINAPP),
  94.         MAKE_SCODE_ENTRY(CO_E_ERRORINDLL),
  95.         MAKE_SCODE_ENTRY(CO_E_IIDSTRING),
  96.         MAKE_SCODE_ENTRY(CO_E_NOTINITIALIZED),
  97.         MAKE_SCODE_ENTRY(CO_E_OBJISREG),
  98.         MAKE_SCODE_ENTRY(CO_E_OBJNOTCONNECTED),
  99.         MAKE_SCODE_ENTRY(CO_E_OBJNOTREG),
  100.         MAKE_SCODE_ENTRY(CO_E_OBJSRV_RPC_FAILURE),
  101.         MAKE_SCODE_ENTRY(CO_E_SCM_ERROR),
  102.         MAKE_SCODE_ENTRY(CO_E_SCM_RPC_FAILURE),
  103.         MAKE_SCODE_ENTRY(CO_E_SERVER_EXEC_FAILURE),
  104.         MAKE_SCODE_ENTRY(CO_E_SERVER_STOPPING),
  105.         MAKE_SCODE_ENTRY(CO_E_WRONGOSFORAPP),
  106.         MAKE_SCODE_ENTRY(CONVERT10_E_OLESTREAM_BITMAP_TO_DIB),
  107.         MAKE_SCODE_ENTRY(CONVERT10_E_OLESTREAM_FMT),
  108.         MAKE_SCODE_ENTRY(CONVERT10_E_OLESTREAM_GET),
  109.         MAKE_SCODE_ENTRY(CONVERT10_E_OLESTREAM_PUT),
  110.         MAKE_SCODE_ENTRY(CONVERT10_E_STG_DIB_TO_BITMAP),
  111.         MAKE_SCODE_ENTRY(CONVERT10_E_STG_FMT),
  112.         MAKE_SCODE_ENTRY(CONVERT10_E_STG_NO_STD_STREAM),
  113.         MAKE_SCODE_ENTRY(DISP_E_ARRAYISLOCKED),
  114.         MAKE_SCODE_ENTRY(DISP_E_BADCALLEE),
  115.         MAKE_SCODE_ENTRY(DISP_E_BADINDEX),
  116.         MAKE_SCODE_ENTRY(DISP_E_BADPARAMCOUNT),
  117.         MAKE_SCODE_ENTRY(DISP_E_BADVARTYPE),
  118.         MAKE_SCODE_ENTRY(DISP_E_EXCEPTION),
  119.         MAKE_SCODE_ENTRY(DISP_E_MEMBERNOTFOUND),
  120.         MAKE_SCODE_ENTRY(DISP_E_NONAMEDARGS),
  121.         MAKE_SCODE_ENTRY(DISP_E_NOTACOLLECTION),
  122.         MAKE_SCODE_ENTRY(DISP_E_OVERFLOW),
  123.         MAKE_SCODE_ENTRY(DISP_E_PARAMNOTFOUND),
  124.         MAKE_SCODE_ENTRY(DISP_E_PARAMNOTOPTIONAL),
  125.         MAKE_SCODE_ENTRY(DISP_E_TYPEMISMATCH),
  126.         MAKE_SCODE_ENTRY(DISP_E_UNKNOWNINTERFACE),
  127.         MAKE_SCODE_ENTRY(DISP_E_UNKNOWNLCID),
  128.         MAKE_SCODE_ENTRY(DISP_E_UNKNOWNNAME),
  129.         MAKE_SCODE_ENTRY(DRAGDROP_E_ALREADYREGISTERED),
  130.         MAKE_SCODE_ENTRY(DRAGDROP_E_INVALIDHWND),
  131.         MAKE_SCODE_ENTRY(DRAGDROP_E_NOTREGISTERED),
  132.         MAKE_SCODE_ENTRY(DV_E_CLIPFORMAT),
  133.         MAKE_SCODE_ENTRY(DV_E_DVASPECT),
  134.         MAKE_SCODE_ENTRY(DV_E_DVTARGETDEVICE),
  135.         MAKE_SCODE_ENTRY(DV_E_DVTARGETDEVICE_SIZE),
  136.         MAKE_SCODE_ENTRY(DV_E_FORMATETC),
  137.         MAKE_SCODE_ENTRY(DV_E_LINDEX),
  138.         MAKE_SCODE_ENTRY(DV_E_NOIVIEWOBJECT),
  139.         MAKE_SCODE_ENTRY(DV_E_STATDATA),
  140.         MAKE_SCODE_ENTRY(DV_E_STGMEDIUM),
  141.         MAKE_SCODE_ENTRY(DV_E_TYMED),
  142.         MAKE_SCODE_ENTRY(INPLACE_E_NOTOOLSPACE),
  143.         MAKE_SCODE_ENTRY(INPLACE_E_NOTUNDOABLE),
  144.         MAKE_SCODE_ENTRY(MEM_E_INVALID_LINK),
  145.         MAKE_SCODE_ENTRY(MEM_E_INVALID_ROOT),
  146.         MAKE_SCODE_ENTRY(MEM_E_INVALID_SIZE),
  147.         MAKE_SCODE_ENTRY(MK_E_CANTOPENFILE),
  148.         MAKE_SCODE_ENTRY(MK_E_CONNECTMANUALLY),
  149.         MAKE_SCODE_ENTRY(MK_E_ENUMERATION_FAILED),
  150.         MAKE_SCODE_ENTRY(MK_E_EXCEEDEDDEADLINE),
  151.         MAKE_SCODE_ENTRY(MK_E_INTERMEDIATEINTERFACENOTSUPPORTED),
  152.         MAKE_SCODE_ENTRY(MK_E_INVALIDEXTENSION),
  153.         MAKE_SCODE_ENTRY(MK_E_MUSTBOTHERUSER),
  154.         MAKE_SCODE_ENTRY(MK_E_NEEDGENERIC),
  155.         MAKE_SCODE_ENTRY(MK_E_NO_NORMALIZED),
  156.         MAKE_SCODE_ENTRY(MK_E_NOINVERSE),
  157.         MAKE_SCODE_ENTRY(MK_E_NOOBJECT),
  158.         MAKE_SCODE_ENTRY(MK_E_NOPREFIX),
  159.         MAKE_SCODE_ENTRY(MK_E_NOSTORAGE),
  160.         MAKE_SCODE_ENTRY(MK_E_NOTBINDABLE),
  161.         MAKE_SCODE_ENTRY(MK_E_NOTBOUND),
  162.         MAKE_SCODE_ENTRY(MK_E_SYNTAX),
  163.         MAKE_SCODE_ENTRY(MK_E_UNAVAILABLE),
  164.         MAKE_SCODE_ENTRY(OLE_E_ADVF),
  165.         MAKE_SCODE_ENTRY(OLE_E_ADVISENOTSUPPORTED),
  166.         MAKE_SCODE_ENTRY(OLE_E_BLANK),
  167.         MAKE_SCODE_ENTRY(OLE_E_CANT_BINDTOSOURCE),
  168.         MAKE_SCODE_ENTRY(OLE_E_CANT_GETMONIKER),
  169.         MAKE_SCODE_ENTRY(OLE_E_CANTCONVERT),
  170.         MAKE_SCODE_ENTRY(OLE_E_CLASSDIFF),
  171.         MAKE_SCODE_ENTRY(OLE_E_ENUM_NOMORE),
  172.         MAKE_SCODE_ENTRY(OLE_E_INVALIDHWND),
  173.         MAKE_SCODE_ENTRY(OLE_E_INVALIDRECT),
  174.         MAKE_SCODE_ENTRY(OLE_E_NOCACHE),
  175.         MAKE_SCODE_ENTRY(OLE_E_NOCONNECTION),
  176.         MAKE_SCODE_ENTRY(OLE_E_NOSTORAGE),
  177.         MAKE_SCODE_ENTRY(OLE_E_NOT_INPLACEACTIVE),
  178.         MAKE_SCODE_ENTRY(OLE_E_NOTRUNNING),
  179.         MAKE_SCODE_ENTRY(OLE_E_OLEVERB),
  180.         MAKE_SCODE_ENTRY(OLE_E_PROMPTSAVECANCELLED),
  181.         MAKE_SCODE_ENTRY(OLE_E_STATIC),
  182.         MAKE_SCODE_ENTRY(OLE_E_WRONGCOMPOBJ),
  183.         MAKE_SCODE_ENTRY(OLEOBJ_E_INVALIDVERB),
  184.         MAKE_SCODE_ENTRY(OLEOBJ_E_NOVERBS),
  185.         MAKE_SCODE_ENTRY(REGDB_E_CLASSNOTREG),
  186.         MAKE_SCODE_ENTRY(REGDB_E_IIDNOTREG),
  187.         MAKE_SCODE_ENTRY(REGDB_E_INVALIDVALUE),
  188.         MAKE_SCODE_ENTRY(REGDB_E_KEYMISSING),
  189.         MAKE_SCODE_ENTRY(REGDB_E_READREGDB),
  190.         MAKE_SCODE_ENTRY(REGDB_E_WRITEREGDB),
  191.         MAKE_SCODE_ENTRY(RPC_E_ATTEMPTED_MULTITHREAD),
  192.         MAKE_SCODE_ENTRY(RPC_E_CALL_CANCELED),
  193.         MAKE_SCODE_ENTRY(RPC_E_CALL_REJECTED),
  194.         MAKE_SCODE_ENTRY(RPC_E_CANTCALLOUT_AGAIN),
  195.         MAKE_SCODE_ENTRY(RPC_E_CANTCALLOUT_INASYNCCALL),
  196.         MAKE_SCODE_ENTRY(RPC_E_CANTCALLOUT_INEXTERNALCALL),
  197.         MAKE_SCODE_ENTRY(RPC_E_CANTCALLOUT_ININPUTSYNCCALL),
  198.         MAKE_SCODE_ENTRY(RPC_E_CANTPOST_INSENDCALL),
  199.         MAKE_SCODE_ENTRY(RPC_E_CANTTRANSMIT_CALL),
  200.         MAKE_SCODE_ENTRY(RPC_E_CHANGED_MODE),
  201.         MAKE_SCODE_ENTRY(RPC_E_CLIENT_CANTMARSHAL_DATA),
  202.         MAKE_SCODE_ENTRY(RPC_E_CLIENT_CANTUNMARSHAL_DATA),
  203.         MAKE_SCODE_ENTRY(RPC_E_CLIENT_DIED),
  204.         MAKE_SCODE_ENTRY(RPC_E_CONNECTION_TERMINATED),
  205.         MAKE_SCODE_ENTRY(RPC_E_DISCONNECTED),
  206.         MAKE_SCODE_ENTRY(RPC_E_FAULT),
  207.         MAKE_SCODE_ENTRY(RPC_E_INVALID_CALLDATA),
  208.         MAKE_SCODE_ENTRY(RPC_E_INVALID_DATA),
  209.         MAKE_SCODE_ENTRY(RPC_E_INVALID_DATAPACKET),
  210.         MAKE_SCODE_ENTRY(RPC_E_INVALID_PARAMETER),
  211.         MAKE_SCODE_ENTRY(RPC_E_INVALIDMETHOD),
  212.         MAKE_SCODE_ENTRY(RPC_E_NOT_REGISTERED),
  213.         MAKE_SCODE_ENTRY(RPC_E_OUT_OF_RESOURCES),
  214.         MAKE_SCODE_ENTRY(RPC_E_RETRY),
  215.         MAKE_SCODE_ENTRY(RPC_E_SERVER_CANTMARSHAL_DATA),
  216.         MAKE_SCODE_ENTRY(RPC_E_SERVER_CANTUNMARSHAL_DATA),
  217.         MAKE_SCODE_ENTRY(RPC_E_SERVER_DIED),
  218.         MAKE_SCODE_ENTRY(RPC_E_SERVER_DIED_DNE),
  219.         MAKE_SCODE_ENTRY(RPC_E_SERVERCALL_REJECTED),
  220.         MAKE_SCODE_ENTRY(RPC_E_SERVERCALL_RETRYLATER),
  221.         MAKE_SCODE_ENTRY(RPC_E_SERVERFAULT),
  222.         MAKE_SCODE_ENTRY(RPC_E_SYS_CALL_FAILED),
  223.         MAKE_SCODE_ENTRY(RPC_E_THREAD_NOT_INIT),
  224.         MAKE_SCODE_ENTRY(RPC_E_UNEXPECTED),
  225.         MAKE_SCODE_ENTRY(RPC_E_WRONG_THREAD),
  226.         MAKE_SCODE_ENTRY(STG_E_ABNORMALAPIEXIT),
  227.         MAKE_SCODE_ENTRY(STG_E_ACCESSDENIED),
  228.         MAKE_SCODE_ENTRY(STG_E_CANTSAVE),
  229.         MAKE_SCODE_ENTRY(STG_E_DISKISWRITEPROTECTED),
  230.         MAKE_SCODE_ENTRY(STG_E_EXTANTMARSHALLINGS),
  231.         MAKE_SCODE_ENTRY(STG_E_FILEALREADYEXISTS),
  232.         MAKE_SCODE_ENTRY(STG_E_FILENOTFOUND),
  233.         MAKE_SCODE_ENTRY(STG_E_INSUFFICIENTMEMORY),
  234.         MAKE_SCODE_ENTRY(STG_E_INUSE),
  235.         MAKE_SCODE_ENTRY(STG_E_INVALIDFLAG),
  236.         MAKE_SCODE_ENTRY(STG_E_INVALIDFUNCTION),
  237.         MAKE_SCODE_ENTRY(STG_E_INVALIDHANDLE),
  238.         MAKE_SCODE_ENTRY(STG_E_INVALIDHEADER),
  239.         MAKE_SCODE_ENTRY(STG_E_INVALIDNAME),
  240.         MAKE_SCODE_ENTRY(STG_E_INVALIDPARAMETER),
  241.         MAKE_SCODE_ENTRY(STG_E_INVALIDPOINTER),
  242.         MAKE_SCODE_ENTRY(STG_E_LOCKVIOLATION),
  243.         MAKE_SCODE_ENTRY(STG_E_MEDIUMFULL),
  244.         MAKE_SCODE_ENTRY(STG_E_NOMOREFILES),
  245.         MAKE_SCODE_ENTRY(STG_E_NOTCURRENT),
  246.         MAKE_SCODE_ENTRY(STG_E_NOTFILEBASEDSTORAGE),
  247.         MAKE_SCODE_ENTRY(STG_E_OLDDLL),
  248.         MAKE_SCODE_ENTRY(STG_E_OLDFORMAT),
  249.         MAKE_SCODE_ENTRY(STG_E_PATHNOTFOUND),
  250.         MAKE_SCODE_ENTRY(STG_E_READFAULT),
  251.         MAKE_SCODE_ENTRY(STG_E_REVERTED),
  252.         MAKE_SCODE_ENTRY(STG_E_SEEKERROR),
  253.         MAKE_SCODE_ENTRY(STG_E_SHAREREQUIRED),
  254.         MAKE_SCODE_ENTRY(STG_E_SHAREVIOLATION),
  255.         MAKE_SCODE_ENTRY(STG_E_TOOMANYOPENFILES),
  256.         MAKE_SCODE_ENTRY(STG_E_UNIMPLEMENTEDFUNCTION),
  257.         MAKE_SCODE_ENTRY(STG_E_UNKNOWN),
  258.         MAKE_SCODE_ENTRY(STG_E_WRITEFAULT),
  259.         MAKE_SCODE_ENTRY(TYPE_E_AMBIGUOUSNAME),
  260.         MAKE_SCODE_ENTRY(TYPE_E_BADMODULEKIND),
  261.         MAKE_SCODE_ENTRY(TYPE_E_BUFFERTOOSMALL),
  262.         MAKE_SCODE_ENTRY(TYPE_E_CANTCREATETMPFILE),
  263.         MAKE_SCODE_ENTRY(TYPE_E_CANTLOADLIBRARY),
  264.         MAKE_SCODE_ENTRY(TYPE_E_CIRCULARTYPE),
  265.         MAKE_SCODE_ENTRY(TYPE_E_DLLFUNCTIONNOTFOUND),
  266.         MAKE_SCODE_ENTRY(TYPE_E_DUPLICATEID),
  267.         MAKE_SCODE_ENTRY(TYPE_E_ELEMENTNOTFOUND),
  268.         MAKE_SCODE_ENTRY(TYPE_E_INCONSISTENTPROPFUNCS),
  269.         MAKE_SCODE_ENTRY(TYPE_E_INVALIDSTATE),
  270.         MAKE_SCODE_ENTRY(TYPE_E_INVDATAREAD),
  271.         MAKE_SCODE_ENTRY(TYPE_E_IOERROR),
  272.         MAKE_SCODE_ENTRY(TYPE_E_LIBNOTREGISTERED),
  273.         MAKE_SCODE_ENTRY(TYPE_E_NAMECONFLICT),
  274.         MAKE_SCODE_ENTRY(TYPE_E_OUTOFBOUNDS),
  275.         MAKE_SCODE_ENTRY(TYPE_E_QUALIFIEDNAMEDISALLOWED),
  276.         MAKE_SCODE_ENTRY(TYPE_E_REGISTRYACCESS),
  277.         MAKE_SCODE_ENTRY(TYPE_E_SIZETOOBIG),
  278.         MAKE_SCODE_ENTRY(TYPE_E_TYPEMISMATCH),
  279.         MAKE_SCODE_ENTRY(TYPE_E_UNDEFINEDTYPE),
  280.         MAKE_SCODE_ENTRY(TYPE_E_UNKNOWNLCID),
  281.         MAKE_SCODE_ENTRY(TYPE_E_UNSUPFORMAT),
  282.         MAKE_SCODE_ENTRY(TYPE_E_WRONGTYPEKIND),
  283.         MAKE_SCODE_ENTRY(VIEW_E_DRAW),
  284.     };
  285.     #undef MAKE_SCODE_ENTRY
  286.  
  287.     // look for it in the table
  288.     for (int i = 0; i < _countof(scNameTable); i++)
  289.     {
  290.         if (sc == scNameTable[i].sc)
  291.             return scNameTable[i].lpszName;
  292.     }
  293.     return NULL;    // not found
  294. }
  295.  
  296. LPCTSTR AFXAPI AfxGetScodeRangeString(SCODE sc)
  297. {
  298.     struct RANGE_ENTRY
  299.     {
  300.         SCODE scFirst;
  301.         SCODE scLast;
  302.         LPCTSTR lpszName;
  303.     };
  304.     #define MAKE_RANGE_ENTRY(scRange) \
  305.         { scRange##_FIRST, scRange##_LAST, \
  306.             _T(#scRange) _T("_FIRST...") _T(#scRange) _T("_LAST") }
  307.  
  308.     static const RANGE_ENTRY scRangeTable[] =
  309.     {
  310.         MAKE_RANGE_ENTRY(CACHE_E),
  311.         MAKE_RANGE_ENTRY(CACHE_S),
  312.         MAKE_RANGE_ENTRY(CLASSFACTORY_E),
  313.         MAKE_RANGE_ENTRY(CLASSFACTORY_S),
  314.         MAKE_RANGE_ENTRY(CLIENTSITE_E),
  315.         MAKE_RANGE_ENTRY(CLIENTSITE_S),
  316.         MAKE_RANGE_ENTRY(CLIPBRD_E),
  317.         MAKE_RANGE_ENTRY(CLIPBRD_S),
  318.         MAKE_RANGE_ENTRY(CONVERT10_E),
  319.         MAKE_RANGE_ENTRY(CONVERT10_S),
  320.         MAKE_RANGE_ENTRY(CO_E),
  321.         MAKE_RANGE_ENTRY(CO_S),
  322.         MAKE_RANGE_ENTRY(DATA_E),
  323.         MAKE_RANGE_ENTRY(DATA_S),
  324.         MAKE_RANGE_ENTRY(DRAGDROP_E),
  325.         MAKE_RANGE_ENTRY(DRAGDROP_S),
  326.         MAKE_RANGE_ENTRY(ENUM_E),
  327.         MAKE_RANGE_ENTRY(ENUM_S),
  328.         MAKE_RANGE_ENTRY(INPLACE_E),
  329.         MAKE_RANGE_ENTRY(INPLACE_S),
  330.         MAKE_RANGE_ENTRY(MARSHAL_E),
  331.         MAKE_RANGE_ENTRY(MARSHAL_S),
  332.         MAKE_RANGE_ENTRY(MK_E),
  333.         MAKE_RANGE_ENTRY(MK_S),
  334.         MAKE_RANGE_ENTRY(OLEOBJ_E),
  335.         MAKE_RANGE_ENTRY(OLEOBJ_S),
  336.         MAKE_RANGE_ENTRY(OLE_E),
  337.         MAKE_RANGE_ENTRY(OLE_S),
  338.         MAKE_RANGE_ENTRY(REGDB_E),
  339.         MAKE_RANGE_ENTRY(REGDB_S),
  340.         MAKE_RANGE_ENTRY(VIEW_E),
  341.         MAKE_RANGE_ENTRY(VIEW_S),
  342.     };
  343.     #undef MAKE_RANGE_ENTRY
  344.  
  345.     // look for it in the table
  346.     for (int i = 0; i < _countof(scRangeTable); i++)
  347.     {
  348.         if (sc >= scRangeTable[i].scFirst && sc <= scRangeTable[i].scLast)
  349.             return scRangeTable[i].lpszName;
  350.     }
  351.     return NULL;    // not found
  352. }
  353.  
  354. LPCTSTR AFXAPI AfxGetSeverityString(SCODE sc)
  355. {
  356.     static const TCHAR* rgszSEVERITY[] =
  357.     {
  358.         _T("SEVERITY_SUCCESS"),
  359.         _T("SEVERITY_ERROR"),
  360.     };
  361.     return rgszSEVERITY[SCODE_SEVERITY(sc)];
  362. }
  363.  
  364. LPCTSTR AFXAPI AfxGetFacilityString(SCODE sc)
  365. {
  366.     static const TCHAR* rgszFACILITY[] =
  367.     {
  368.         _T("FACILITY_NULL"),
  369.         _T("FACILITY_RPC"),
  370.         _T("FACILITY_DISPATCH"),
  371.         _T("FACILITY_STORAGE"),
  372.         _T("FACILITY_ITF"),
  373.         _T("FACILITY_0x05"),
  374.         _T("FACILITY_0x06"),
  375.         _T("FACILITY_WIN32"),
  376.         _T("FACILITY_WINDOWS"),
  377.     };
  378.     if (SCODE_FACILITY(sc) >= _countof(rgszFACILITY))
  379.         return _T("<Unknown Facility>");
  380.  
  381.     return rgszFACILITY[SCODE_FACILITY(sc)];
  382. }
  383.  
  384. LPCTSTR AFXAPI AfxGetFullScodeString(SCODE sc)
  385. {
  386.     static TCHAR szBuf[128];
  387.     LPCTSTR lpsz;
  388.     if ((lpsz = AfxGetScodeString(sc)) != NULL)
  389.     {
  390.         // found exact match
  391.         wsprintf(szBuf, _T("%s ($%08lX)"), lpsz, sc);
  392.     }
  393.     else if ((lpsz = AfxGetScodeRangeString(sc)) != NULL)
  394.     {
  395.         // found suitable range
  396.         wsprintf(szBuf, _T("range: %s ($%08lX)"), lpsz, sc);
  397.     }
  398.     else
  399.     {
  400.         // not found at all -- split it up into its parts
  401.         wsprintf(szBuf, _T("severity: %s, facility: %s ($%08lX)"),
  402.             AfxGetSeverityString(sc), AfxGetFacilityString(sc), sc);
  403.     }
  404.     return szBuf;
  405. }
  406. #endif //_DEBUG
  407.  
  408. /////////////////////////////////////////////////////////////////////////////
  409. // Exceptions for OLE Support
  410.  
  411. void AFXAPI AfxThrowOleException(SCODE sc)
  412. {
  413. #ifdef _DEBUG
  414.     TRACE1("Warning: constructing COleException, scode = %s.\n",
  415.         AfxGetFullScodeString(sc));
  416. #endif
  417.     COleException* pException = new COleException;
  418.     pException->m_sc = sc;
  419.     THROW(pException);
  420. }
  421.  
  422. BOOL COleException::GetErrorMessage(LPTSTR lpszError, UINT nMaxError,
  423.         PUINT pnHelpContext)
  424. {
  425.     ASSERT(lpszError != NULL && AfxIsValidString(lpszError, nMaxError));
  426.  
  427.     if (pnHelpContext != NULL)
  428.         *pnHelpContext = 0;
  429.  
  430.     LPTSTR lpBuffer;
  431.     if (::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
  432.                 FORMAT_MESSAGE_FROM_SYSTEM,
  433.                 NULL, m_sc,
  434.                 MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT),
  435.                 (LPTSTR) &lpBuffer, 0, NULL) == 0)
  436.     {
  437.         *lpszError = '\0';
  438.         return FALSE;
  439.     }
  440.     else
  441.     {
  442.         lstrcpyn(lpszError, lpBuffer, nMaxError);
  443.         LocalFree(lpBuffer);
  444.         return TRUE;
  445.     }
  446. }
  447.  
  448. /////////////////////////////////////////////////////////////////////////////
  449. // Turn a caught exception into an OLE return code
  450.  
  451. SCODE PASCAL COleException::Process(const CException* pAnyException)
  452. {
  453.     SCODE sc;
  454.     if (pAnyException->IsKindOf(RUNTIME_CLASS(COleException)))
  455.         sc = ((COleException*)pAnyException)->m_sc;
  456.     else if (pAnyException->IsKindOf(RUNTIME_CLASS(CMemoryException)))
  457.         sc = E_OUTOFMEMORY;
  458.     else if (pAnyException->IsKindOf(RUNTIME_CLASS(CNotSupportedException)))
  459.         sc = E_NOTIMPL;
  460.     else
  461.         sc = E_UNEXPECTED;  // some other problem
  462.  
  463.     return sc;
  464. }
  465.  
  466. /////////////////////////////////////////////////////////////////////////////
  467. // Implementation helpers
  468.  
  469. HMENU AFXAPI AfxMergeMenus(HMENU hMenuShared, HMENU hMenuSource,
  470.     LONG* lpMenuWidths, int iWidthIndex, BOOL bMergeHelpMenus /* = FALSE */)
  471. {
  472.     ASSERT(hMenuShared != NULL && IsMenu(hMenuShared));
  473.     ASSERT(hMenuSource != NULL && IsMenu(hMenuSource));
  474.  
  475.     BOOL bHelpMergedAsSubMenu = FALSE;
  476.     HMENU hHelpSubMenu = NULL;
  477.  
  478.     // copy the popups from the pMenuSource
  479.     int cMenuItems = GetMenuItemCount(hMenuSource);
  480.     int cGroupWidth = 0;
  481.     int nPosition = 0;
  482.  
  483.     // insert at appropriate spot depending on iWidthIndex
  484.     ASSERT(iWidthIndex == 0 || iWidthIndex == 1);
  485.     if (iWidthIndex == 1)
  486.         nPosition = (int)lpMenuWidths[0];
  487.  
  488.     for (int i = 0; i < cMenuItems; i++)
  489.     {
  490.         // get the HMENU of the popup
  491.         HMENU hMenuPopup = ::GetSubMenu(hMenuSource, i);
  492.  
  493.         // separators move us to next group
  494.         UINT state = GetMenuState(hMenuSource, i, MF_BYPOSITION);
  495.         if (hMenuPopup == NULL && (state & MF_SEPARATOR) != 0)
  496.         {
  497.             ASSERT(iWidthIndex <= 5);   // servers should not touch past 5
  498.             lpMenuWidths[iWidthIndex] = cGroupWidth;
  499.             cGroupWidth = 0;
  500.             if (iWidthIndex < 5)
  501.                 nPosition += (int)lpMenuWidths[iWidthIndex+1];
  502.             iWidthIndex += 2;
  503.         }
  504.         else
  505.         {
  506.             HMENU hHelpMenu = NULL;
  507.  
  508.             // are we processing the help menu group?
  509.  
  510.             if (bMergeHelpMenus && iWidthIndex == 5)
  511.             {
  512.                 // if so, see if the container has Help any menu items
  513.                 if (lpMenuWidths[iWidthIndex] == 1)
  514.                 {
  515.                     // get the help menu from the container
  516.                     hHelpMenu = GetSubMenu(hMenuShared, nPosition);
  517.                 }
  518.             }
  519.  
  520.             // get the menu item text
  521.             TCHAR szItemText[256];
  522.             int nLen = GetMenuString(hMenuSource, i, szItemText,
  523.                 sizeof szItemText, MF_BYPOSITION);
  524.  
  525.             // popups are handled differently than normal menu items
  526.             if (hMenuPopup != NULL)
  527.             {
  528.                 if (hHelpMenu != NULL)
  529.                 {
  530.                     CString strTearOff = AfxGetAppName();
  531.                     if (!strTearOff.IsEmpty())
  532.                         strTearOff += ' ';
  533.                     strTearOff += szItemText;
  534.  
  535.                     // container has help items -- add ours to its submenu
  536.                     AppendMenu(hHelpMenu, MF_STRING | MF_POPUP,
  537.                         (UINT)hMenuPopup, strTearOff);
  538.  
  539.                     // clear the count of Help group items and add
  540.                     // the help menu to the window group
  541.  
  542.                     lpMenuWidths[iWidthIndex] = 0;
  543.                     lpMenuWidths[iWidthIndex-1]++;
  544.  
  545.                     bHelpMergedAsSubMenu = TRUE;
  546.                     hHelpSubMenu = hMenuPopup;
  547.                 }
  548.                 else if (::GetMenuItemCount(hMenuPopup) != 0)
  549.                 {
  550.                     // strip the HIBYTE because it contains a count of items
  551.                     state = LOBYTE(state) | MF_POPUP;   // must be popup
  552.  
  553.                     // non-empty popup -- add it to the shared menu bar
  554.                     InsertMenu(hMenuShared, nPosition, state | MF_BYPOSITION,
  555.                         (UINT)hMenuPopup, szItemText);
  556.                     ++nPosition;
  557.                     ++cGroupWidth;
  558.                 }
  559.             }
  560.             else if (nLen > 0)
  561.             {
  562.                 // only non-empty items are added
  563.                 ASSERT(szItemText[0] != 0);
  564.  
  565.                 // here the state does not contain a count in the HIBYTE
  566.                 InsertMenu(hMenuShared, nPosition, state | MF_BYPOSITION,
  567.                     GetMenuItemID(hMenuSource, i), szItemText);
  568.                 ++nPosition;
  569.                 ++cGroupWidth;
  570.             }
  571.         }
  572.     }
  573.  
  574.     // set the last group width
  575.  
  576.     if (!bHelpMergedAsSubMenu)
  577.     {
  578.         ASSERT(iWidthIndex <= 5);   // servers should not touch past 5
  579.         lpMenuWidths[iWidthIndex] = cGroupWidth;
  580.     }
  581.  
  582.     return hHelpSubMenu;
  583. }
  584.  
  585. void AFXAPI AfxUnmergeMenus(HMENU hMenuShared, HMENU hMenuSource,
  586.     HMENU hHelpMenuPopup /* = NULL */)
  587. {
  588.     ASSERT(hMenuShared != NULL && IsMenu(hMenuShared));
  589.     ASSERT(hMenuSource != NULL && IsMenu(hMenuSource));
  590.     ASSERT(hHelpMenuPopup == NULL || IsMenu(hHelpMenuPopup));
  591.  
  592.     int cOurItems = GetMenuItemCount(hMenuSource);
  593.     int cMenuItems = GetMenuItemCount(hMenuShared);
  594.  
  595.     for (int i = cMenuItems-1; i >= 0; i--)
  596.     {
  597.         // check out the popup menus
  598.         HMENU hMenuPopup = ::GetSubMenu(hMenuShared, i);
  599.         if (hMenuPopup != NULL)
  600.         {
  601.             // if we have a Help submenu, check to see if it appears in this
  602.             // submenu someplace... this normally happens only in
  603.             // DocObject frame windows
  604.  
  605.             if (hHelpMenuPopup != NULL)
  606.             {
  607.                 int cPopupItems = ::GetMenuItemCount(hMenuPopup);
  608.                 for (int k = 0; k < cPopupItems; k++)
  609.                 {
  610.                     if (::GetSubMenu(hMenuPopup, k) == hHelpMenuPopup)
  611.                     {
  612.                         ::RemoveMenu(hMenuPopup, k, MF_BYPOSITION);
  613.                         hHelpMenuPopup = NULL;  // can only have one
  614.                         break;
  615.                     }
  616.                 }
  617.             }
  618.             else
  619.             {
  620.                 // if it is one of ours, remove it from the pMenuShared
  621.                 for (int j = 0; j < cOurItems; j++)
  622.                 {
  623.                     if (::GetSubMenu(hMenuSource, j) == hMenuPopup)
  624.                     {
  625.                         // remove the menu from pMenuShared
  626.                         RemoveMenu(hMenuShared, i, MF_BYPOSITION);
  627.                         break;
  628.                     }
  629.                 }
  630.             }
  631.         }
  632.     }
  633. }
  634.  
  635. // Helper for creating default FORMATETC from cfFormat
  636. LPFORMATETC AFXAPI _AfxFillFormatEtc(
  637.     LPFORMATETC lpFormatEtc, CLIPFORMAT cfFormat, LPFORMATETC lpFormatEtcFill)
  638. {
  639.     ASSERT(lpFormatEtcFill != NULL);
  640.     if (lpFormatEtc == NULL && cfFormat != 0)
  641.     {
  642.         lpFormatEtc = lpFormatEtcFill;
  643.         lpFormatEtc->cfFormat = cfFormat;
  644.         lpFormatEtc->ptd = NULL;
  645.         lpFormatEtc->dwAspect = DVASPECT_CONTENT;
  646.         lpFormatEtc->lindex = -1;
  647.         lpFormatEtc->tymed = (DWORD) -1;
  648.     }
  649.     return lpFormatEtc;
  650. }
  651.  
  652. AFX_STATIC HGLOBAL AFXAPI _AfxCopyGlobalMemory(HGLOBAL hDest, HGLOBAL hSource)
  653. {
  654.     ASSERT(hSource != NULL);
  655.  
  656.     // make sure we have suitable hDest
  657.     DWORD nSize = ::GlobalSize(hSource);
  658.     if (hDest == NULL)
  659.     {
  660.         hDest = ::GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, nSize);
  661.         if (hDest == NULL)
  662.             return NULL;
  663.     }
  664.     else if (nSize > ::GlobalSize(hDest))
  665.     {
  666.         // hDest is not large enough
  667.         return NULL;
  668.     }
  669.  
  670.     // copy the bits
  671.     LPVOID lpSource = ::GlobalLock(hSource);
  672.     LPVOID lpDest = ::GlobalLock(hDest);
  673.     ASSERT(lpDest != NULL);
  674.     ASSERT(lpSource != NULL);
  675.     memcpy(lpDest, lpSource, nSize);
  676.     ::GlobalUnlock(hDest);
  677.     ::GlobalUnlock(hSource);
  678.  
  679.     // success -- return hDest
  680.     return hDest;
  681. }
  682.  
  683. BOOL AFXAPI _AfxCopyStgMedium(
  684.     CLIPFORMAT cfFormat, LPSTGMEDIUM lpDest, LPSTGMEDIUM lpSource)
  685. {
  686.     if (lpDest->tymed == TYMED_NULL)
  687.     {
  688.         ASSERT(lpSource->tymed != TYMED_NULL);
  689.         switch (lpSource->tymed)
  690.         {
  691.         case TYMED_ENHMF:
  692.         case TYMED_HGLOBAL:
  693.             ASSERT(sizeof(HGLOBAL) == sizeof(HENHMETAFILE));
  694.             lpDest->tymed = lpSource->tymed;
  695.             lpDest->hGlobal = NULL;
  696.             break;  // fall through to CopyGlobalMemory case
  697.  
  698.         case TYMED_ISTREAM:
  699.             lpDest->pstm = lpSource->pstm;
  700.             lpDest->pstm->AddRef();
  701.             lpDest->tymed = TYMED_ISTREAM;
  702.             return TRUE;
  703.  
  704.         case TYMED_ISTORAGE:
  705.             lpDest->pstg = lpSource->pstg;
  706.             lpDest->pstg->AddRef();
  707.             lpDest->tymed = TYMED_ISTORAGE;
  708.             return TRUE;
  709.  
  710.         case TYMED_MFPICT:
  711.             {
  712.                 // copy LPMETAFILEPICT struct + embedded HMETAFILE
  713.                 HGLOBAL hDest = _AfxCopyGlobalMemory(NULL, lpSource->hGlobal);
  714.                 if (hDest == NULL)
  715.                     return FALSE;
  716.                 LPMETAFILEPICT lpPict = (LPMETAFILEPICT)::GlobalLock(hDest);
  717.                 ASSERT(lpPict != NULL);
  718.                 lpPict->hMF = ::CopyMetaFile(lpPict->hMF, NULL);
  719.                 if (lpPict->hMF == NULL)
  720.                 {
  721.                     ::GlobalUnlock(hDest);
  722.                     ::GlobalFree(hDest);
  723.                     return FALSE;
  724.                 }
  725.                 ::GlobalUnlock(hDest);
  726.  
  727.                 // fill STGMEDIUM struct
  728.                 lpDest->hGlobal = hDest;
  729.                 lpDest->tymed = TYMED_MFPICT;
  730.             }
  731.             return TRUE;
  732.  
  733.         case TYMED_GDI:
  734.             lpDest->tymed = TYMED_GDI;
  735.             lpDest->hGlobal = NULL;
  736.             break;
  737.  
  738.         case TYMED_FILE:
  739.             {
  740.                 USES_CONVERSION;
  741.                 lpDest->tymed = TYMED_FILE;
  742.                 ASSERT(lpSource->lpszFileName != NULL);
  743.                 UINT cbSrc = ocslen(lpSource->lpszFileName);
  744.                 LPOLESTR szFileName = (LPOLESTR)CoTaskMemAlloc(cbSrc*sizeof(OLECHAR));
  745.                 lpDest->lpszFileName = szFileName;
  746.                 if (szFileName == NULL)
  747.                     return FALSE;
  748.                 memcpy(szFileName, lpSource->lpszFileName,  (cbSrc+1)*sizeof(OLECHAR));
  749.                 return TRUE;
  750.             }
  751.  
  752.         // unable to create + copy other TYMEDs
  753.         default:
  754.             return FALSE;
  755.         }
  756.     }
  757.     ASSERT(lpDest->tymed == lpSource->tymed);
  758.  
  759.     switch (lpSource->tymed)
  760.     {
  761.     case TYMED_HGLOBAL:
  762.         {
  763.             HGLOBAL hDest = _AfxCopyGlobalMemory(lpDest->hGlobal,
  764.                 lpSource->hGlobal);
  765.             if (hDest == NULL)
  766.                 return FALSE;
  767.  
  768.             lpDest->hGlobal = hDest;
  769.         }
  770.         return TRUE;
  771.  
  772.     case TYMED_ISTREAM:
  773.         {
  774.             ASSERT(lpDest->pstm != NULL);
  775.             ASSERT(lpSource->pstm != NULL);
  776.  
  777.             // get the size of the source stream
  778.             STATSTG stat;
  779.             if (lpSource->pstm->Stat(&stat, STATFLAG_NONAME) != S_OK)
  780.             {
  781.                 // unable to get size of source stream
  782.                 return FALSE;
  783.             }
  784.             ASSERT(stat.pwcsName == NULL);
  785.  
  786.             // always seek to zero before copy
  787.             LARGE_INTEGER zero = { 0, 0 };
  788.             lpDest->pstm->Seek(zero, STREAM_SEEK_SET, NULL);
  789.             lpSource->pstm->Seek(zero, STREAM_SEEK_SET, NULL);
  790.  
  791.             // copy source to destination
  792.             if (lpSource->pstm->CopyTo(lpDest->pstm, stat.cbSize,
  793.                 NULL, NULL) != NULL)
  794.             {
  795.                 // copy from source to dest failed
  796.                 return FALSE;
  797.             }
  798.  
  799.             // always seek to zero after copy
  800.             lpDest->pstm->Seek(zero, STREAM_SEEK_SET, NULL);
  801.             lpSource->pstm->Seek(zero, STREAM_SEEK_SET, NULL);
  802.         }
  803.         return TRUE;
  804.  
  805.     case TYMED_ISTORAGE:
  806.         {
  807.             ASSERT(lpDest->pstg != NULL);
  808.             ASSERT(lpSource->pstg != NULL);
  809.  
  810.             // just copy source to destination
  811.             if (lpSource->pstg->CopyTo(0, NULL, NULL, lpDest->pstg) != S_OK)
  812.                 return FALSE;
  813.         }
  814.         return TRUE;
  815.  
  816.     case TYMED_FILE:
  817.         {
  818.             USES_CONVERSION;
  819.             ASSERT(lpSource->lpszFileName != NULL);
  820.             ASSERT(lpDest->lpszFileName != NULL);
  821.             return CopyFile(OLE2T(lpSource->lpszFileName), OLE2T(lpDest->lpszFileName), FALSE);
  822.         }
  823.  
  824.  
  825.     case TYMED_ENHMF:
  826.     case TYMED_GDI:
  827.         {
  828.             ASSERT(sizeof(HGLOBAL) == sizeof(HENHMETAFILE));
  829.  
  830.             // with TYMED_GDI cannot copy into existing HANDLE
  831.             if (lpDest->hGlobal != NULL)
  832.                 return FALSE;
  833.  
  834.             // otherwise, use OleDuplicateData for the copy
  835.             lpDest->hGlobal = OleDuplicateData(lpSource->hGlobal, cfFormat, 0);
  836.             if (lpDest->hGlobal == NULL)
  837.                 return FALSE;
  838.         }
  839.         return TRUE;
  840.  
  841.     // other TYMEDs cannot be copied
  842.     default:
  843.         return FALSE;
  844.     }
  845. }
  846.  
  847. /////////////////////////////////////////////////////////////////////////////
  848. // OLE utility functions (some borrowed from OLE2UI library)
  849.  
  850. HGLOBAL AFXAPI _AfxOleGetObjectDescriptorData(
  851.     CLSID       clsid,
  852.     DWORD       dwDrawAspect,
  853.     SIZEL       sizel,
  854.     POINTL      pointl,
  855.     DWORD       dwStatus,
  856.     LPCOLESTR   lpszFullUserTypeName,
  857.     LPCOLESTR   lpszSrcOfCopy)
  858. {
  859.     HGLOBAL     hMem = NULL;
  860.     LPOBJECTDESCRIPTOR lpOD;
  861.     DWORD       dwObjectDescSize, dwFullUserTypeNameLen, dwSrcOfCopyLen;
  862.  
  863.     // Get the length of Full User Type Name; Add 1 for the null terminator
  864.     dwFullUserTypeNameLen = lpszFullUserTypeName ?
  865.         ocslen(lpszFullUserTypeName)+1 : 0;
  866.  
  867.     // Get the Source of Copy string and it's length;
  868.     //  Add 1 for the null terminator
  869.     if (lpszSrcOfCopy && lpszSrcOfCopy[0] != '\0')
  870.        dwSrcOfCopyLen = ocslen(lpszSrcOfCopy)+1;
  871.     else
  872.     {
  873.        // No src moniker so use user type name as source string.
  874.        lpszSrcOfCopy =  lpszFullUserTypeName;
  875.        dwSrcOfCopyLen = dwFullUserTypeNameLen;
  876.     }
  877.  
  878.     // Allocate space for OBJECTDESCRIPTOR and the additional string data
  879.     dwObjectDescSize = sizeof(OBJECTDESCRIPTOR);
  880.     hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE | GMEM_ZEROINIT,
  881.        dwObjectDescSize + (dwFullUserTypeNameLen + dwSrcOfCopyLen) *
  882.         sizeof(OLECHAR));
  883.     if (!hMem)
  884.         return NULL;
  885.  
  886.     lpOD = (LPOBJECTDESCRIPTOR)GlobalLock(hMem);
  887.  
  888.     // Set the FullUserTypeName offset and copy the string
  889.     if (lpszFullUserTypeName)
  890.     {
  891.         lpOD->dwFullUserTypeName = dwObjectDescSize;
  892.         ocscpy((LPOLESTR)((LPBYTE)lpOD+lpOD->dwFullUserTypeName), lpszFullUserTypeName);
  893.     }
  894.     else
  895.         lpOD->dwFullUserTypeName = 0;  // zero offset indicates that string is not present
  896.  
  897.     // Set the SrcOfCopy offset and copy the string
  898.     if (lpszSrcOfCopy)
  899.     {
  900.         lpOD->dwSrcOfCopy = dwObjectDescSize + dwFullUserTypeNameLen * sizeof(OLECHAR);
  901.         ocscpy((LPOLESTR)((LPBYTE)lpOD+lpOD->dwSrcOfCopy), lpszSrcOfCopy);
  902.     }
  903.     else
  904.         lpOD->dwSrcOfCopy = 0;  // zero offset indicates that string is not present
  905.  
  906.     // Initialize the rest of the OBJECTDESCRIPTOR
  907.     lpOD->cbSize       = dwObjectDescSize +
  908.         (dwFullUserTypeNameLen + dwSrcOfCopyLen) * sizeof(OLECHAR);
  909.     lpOD->clsid        = clsid;
  910.     lpOD->dwDrawAspect = dwDrawAspect;
  911.     lpOD->sizel        = sizel;
  912.     lpOD->pointl       = pointl;
  913.     lpOD->dwStatus     = dwStatus;
  914.  
  915.     GlobalUnlock(hMem);
  916.     return hMem;
  917. }
  918.  
  919. HGLOBAL AFXAPI _AfxOleGetObjectDescriptorData(
  920.     LPOLEOBJECT     lpOleObj,
  921.     LPCOLESTR       lpszSrcOfCopy,
  922.     DWORD           dwDrawAspect,
  923.     POINTL          pointl,
  924.     LPSIZEL         lpSizelHim)
  925. {
  926.     USES_CONVERSION;
  927.  
  928.     CLSID           clsid;
  929.     LPOLESTR        lpszFullUserTypeName = NULL;
  930.     LPMONIKER       lpSrcMonikerOfCopy = NULL;
  931.     HGLOBAL         hObjDesc = NULL;
  932.     IBindCtx        *pbc = NULL;
  933.     SCODE           sc;
  934.     SIZEL           sizelHim;
  935.     BOOL            bFreeSrcOfCopy = FALSE;
  936.     LPVIEWOBJECT2   lpViewObj2;
  937.     LPOLELINK       lpOleLink;
  938.     BOOL            fIsLink;
  939.     TCHAR           szLinkedTypeFmt[80];
  940.     LPCOLESTR       lpszLinkedTypeFmt;
  941.     LPOLESTR        lpszBuf = NULL;
  942.     DWORD           dwStatus = 0;
  943.  
  944.     // query for IOleLink
  945.     lpOleLink = QUERYINTERFACE(lpOleObj, IOleLink);
  946.     fIsLink = lpOleLink != NULL;
  947.  
  948.     // query for IViewObject2
  949.     lpViewObj2 = QUERYINTERFACE(lpOleObj, IViewObject2);
  950.  
  951.     // Get CLSID
  952.     sc = lpOleObj->GetUserClassID(&clsid);
  953.     if (sc != S_OK)
  954.         clsid = CLSID_NULL;
  955.  
  956.     // Get FullUserTypeName
  957.     sc = lpOleObj->GetUserType(USERCLASSTYPE_FULL, &lpszFullUserTypeName);
  958.  
  959.     // if object is a link, then expand usertypename to be "Linked %s"
  960.     if (fIsLink && lpszFullUserTypeName != NULL)
  961.     {
  962.         // Note: If this LoadString call fails, it is likely that
  963.         //  _AFX_NO_OLE_RESOURCES is defined in your .RC file.
  964.         // To correct the situation remove the following line from your
  965.         //  resource script:
  966.         //      #define _AFX_NO_OLE_RESOURCES
  967.         // This should be done using the Resource.Set Includes... command.
  968.  
  969.         VERIFY(AfxLoadString(AFX_IDS_PASTELINKEDTYPE, szLinkedTypeFmt));
  970.         lpszLinkedTypeFmt = T2COLE(szLinkedTypeFmt);
  971.         lpszBuf = (LPOLESTR)CoTaskMemAlloc((ocslen(lpszFullUserTypeName) +
  972.             ocslen(lpszLinkedTypeFmt) + 1) * sizeof(OLECHAR));
  973.         if (lpszBuf != NULL)
  974.         {
  975. #ifdef OLE2ANSI
  976.             sprintf(lpszBuf, lpszLinkedTypeFmt, lpszFullUserTypeName);
  977. #else
  978.             swprintf(lpszBuf, lpszLinkedTypeFmt, lpszFullUserTypeName);
  979. #endif
  980.             CoTaskMemFree(lpszFullUserTypeName);
  981.             lpszFullUserTypeName = lpszBuf;
  982.         }
  983.     }
  984.  
  985.     // get source of copy
  986.     if (fIsLink)
  987.     {
  988.         sc = lpOleLink->GetSourceDisplayName((LPOLESTR*)&lpszSrcOfCopy);
  989.         bFreeSrcOfCopy = TRUE;
  990.     }
  991.     else if (lpszSrcOfCopy == NULL)
  992.     {
  993.         sc = lpOleObj->GetMoniker(
  994.             OLEGETMONIKER_TEMPFORUSER, OLEWHICHMK_OBJFULL, &lpSrcMonikerOfCopy);
  995.         if (sc == S_OK)
  996.         {
  997.             CreateBindCtx(0, &pbc);
  998.             lpSrcMonikerOfCopy->GetDisplayName(pbc, NULL,
  999.                 (LPOLESTR*)&lpszSrcOfCopy);
  1000.             RELEASE(pbc);
  1001.             bFreeSrcOfCopy = TRUE;
  1002.         }
  1003.     }
  1004.  
  1005.     if (lpSizelHim)
  1006.     {
  1007.         // Use extents passed by the caller
  1008.         sizelHim = *lpSizelHim;
  1009.     }
  1010.     else if (lpViewObj2)
  1011.     {
  1012.         // Get the current extents from the object
  1013.         sc = lpViewObj2->GetExtent(dwDrawAspect, -1, NULL,
  1014.             (LPSIZEL)&sizelHim);
  1015.         if (sc != S_OK)
  1016.             sizelHim.cx = sizelHim.cy = 0;
  1017.     }
  1018.     else
  1019.     {
  1020.         sizelHim.cx = sizelHim.cy = 0;
  1021.     }
  1022.  
  1023.     // Get dwStatus
  1024.     sc = lpOleObj->GetMiscStatus(dwDrawAspect, &dwStatus);
  1025.     if (sc != S_OK)
  1026.         dwStatus = 0;
  1027.  
  1028.     // Get OBJECTDESCRIPTOR
  1029.     hObjDesc = _AfxOleGetObjectDescriptorData(clsid, dwDrawAspect, sizelHim,
  1030.         pointl, dwStatus, lpszFullUserTypeName, lpszSrcOfCopy);
  1031.  
  1032.     // Clean up
  1033.     CoTaskMemFree(lpszFullUserTypeName);
  1034.     if (bFreeSrcOfCopy)
  1035.         CoTaskMemFree((LPOLESTR)lpszSrcOfCopy);
  1036.     RELEASE(lpSrcMonikerOfCopy);
  1037.     RELEASE(lpOleLink);
  1038.     RELEASE(lpViewObj2);
  1039.  
  1040.     return hObjDesc;
  1041. }
  1042.  
  1043. SCODE AFXAPI _AfxOleDoConvert(LPSTORAGE lpStg, REFCLSID rClsidNew)
  1044. {
  1045.     SCODE sc;
  1046.     CLSID clsidOld;
  1047.     if ((sc = ReadClassStg(lpStg, &clsidOld)) != S_OK)
  1048.     {
  1049.         clsidOld = CLSID_NULL;
  1050.         return sc;
  1051.     }
  1052.  
  1053.     // read old fmt/old user type; sets out params to NULL on error
  1054.     CLIPFORMAT cfOld;
  1055.     LPOLESTR lpszOld = NULL;
  1056.     sc = ReadFmtUserTypeStg(lpStg, &cfOld, &lpszOld);
  1057.     ASSERT(sc == S_OK || (cfOld == 0 && lpszOld == NULL));
  1058.  
  1059.     // get new user type name; if error, set to NULL string
  1060.     OLECHAR chZero = 0;
  1061.     LPOLESTR lpszNew = NULL;
  1062.     if (OleRegGetUserType(rClsidNew, USERCLASSTYPE_FULL, &lpszNew) != S_OK)
  1063.         lpszNew = &chZero;
  1064.  
  1065.     // write class stg
  1066.     if ((sc = WriteClassStg(lpStg, rClsidNew)) != S_OK)
  1067.         goto ErrorReturn;
  1068.  
  1069.     // write old fmt/new user type;
  1070.     if ((sc = WriteFmtUserTypeStg(lpStg, cfOld, lpszNew)) != S_OK)
  1071.         goto RewriteInfo;
  1072.  
  1073.     // set convert bit
  1074.     if ((sc = SetConvertStg(lpStg, TRUE)) != S_OK)
  1075.         goto RewriteInfo;
  1076.  
  1077.     goto ErrorReturn;
  1078.  
  1079. RewriteInfo:
  1080.     WriteClassStg(lpStg, clsidOld);
  1081.     WriteFmtUserTypeStg(lpStg, cfOld, lpszOld);
  1082.  
  1083. ErrorReturn:
  1084.     if (lpszNew != &chZero)
  1085.         CoTaskMemFree(lpszNew);
  1086.  
  1087.     CoTaskMemFree(lpszOld);
  1088.     return sc;
  1089. }
  1090.  
  1091. SCODE AFXAPI _AfxOleDoTreatAsClass(
  1092.     LPCTSTR lpszUserType, REFCLSID rclsid, REFCLSID rclsidNew)
  1093. {
  1094.     LPTSTR  lpszCLSID = NULL;
  1095.     HKEY    hKey;
  1096.  
  1097.     SCODE sc = CoTreatAsClass(rclsid, rclsidNew);
  1098.     if (sc != S_OK && lpszUserType != NULL)
  1099.     {
  1100.         RegOpenKey(HKEY_CLASSES_ROOT, _T("CLSID"), &hKey);
  1101.         LPOLESTR lpOleStr = NULL;
  1102.         StringFromCLSID(rclsid, &lpOleStr);
  1103.         lpszCLSID = TASKSTRINGOLE2T(lpOleStr);
  1104.         RegSetValue(hKey, lpszCLSID, REG_SZ, lpszUserType,
  1105.             lstrlen(lpszUserType) * sizeof(TCHAR));
  1106.  
  1107.         CoTaskMemFree(lpszCLSID);
  1108.         sc = CoTreatAsClass(rclsid, rclsidNew);
  1109.         RegCloseKey(hKey);
  1110.     }
  1111.     return sc;
  1112. }
  1113.  
  1114. #define DEVNAMEPART(pdn, x) (pdn->x == 0 ? NULL : (LPCTSTR)pdn + pdn->x)
  1115.  
  1116. DVTARGETDEVICE* AFXAPI _AfxOleCreateTargetDevice(LPDEVNAMES pDN, LPDEVMODE pDM)
  1117. {
  1118.     USES_CONVERSION;
  1119.  
  1120.     DVTARGETDEVICE* ptd = NULL;
  1121.     DWORD dwDevNamesSize, dwDevModeSize, dwPtdSize;
  1122.  
  1123.     LPCTSTR lpszDriverName = DEVNAMEPART(pDN, wDriverOffset);
  1124.     LPCTSTR lpszDeviceName = DEVNAMEPART(pDN, wDeviceOffset);
  1125.     LPCTSTR lpszPortName = DEVNAMEPART(pDN, wOutputOffset);
  1126.  
  1127.     LPCOLESTR lpszDriverNameOle = T2COLE(lpszDriverName);
  1128.     LPCOLESTR lpszDeviceNameOle = T2COLE(lpszDeviceName);
  1129.     LPCOLESTR lpszPortNameOle = T2COLE(lpszPortName);
  1130.     int nDriverNameSize = (lpszDriverNameOle == NULL) ? 0 : (ocslen(lpszDriverNameOle)+1)*sizeof(OLECHAR);
  1131.     int nDeviceNameSize = (lpszDeviceNameOle == NULL) ? 0 : (ocslen(lpszDeviceNameOle)+1)*sizeof(OLECHAR);
  1132.     int nPortNameSize = (lpszPortNameOle == NULL) ? 0 : (ocslen(lpszPortNameOle)+1)*sizeof(OLECHAR);
  1133.  
  1134.     LPDEVMODEOLE lpDevModeOle = DEVMODET2OLE(pDM);
  1135.  
  1136.     dwDevNamesSize = nDriverNameSize + nDeviceNameSize + nPortNameSize;
  1137.     dwDevModeSize = (DWORD)(lpDevModeOle->dmSize + lpDevModeOle->dmDriverExtra);
  1138.  
  1139.     dwPtdSize = sizeof(DVTARGETDEVICE) + dwDevNamesSize + dwDevModeSize;
  1140.  
  1141.     if ((ptd = (DVTARGETDEVICE*)CoTaskMemAlloc(dwPtdSize)) != NULL)
  1142.     {
  1143.         // copy in the info
  1144.         ptd->tdSize = (UINT)dwPtdSize;
  1145.  
  1146.         ptd->tdDriverNameOffset = sizeof(DVTARGETDEVICE);
  1147.         ocscpy((LPOLESTR)((BYTE*)ptd + ptd->tdDriverNameOffset), lpszDriverNameOle);
  1148.         ptd->tdDeviceNameOffset = (WORD)(ptd->tdDriverNameOffset + nDriverNameSize);
  1149.         ocscpy((LPOLESTR)((BYTE*)ptd + ptd->tdDeviceNameOffset), lpszDeviceNameOle);
  1150.         ptd->tdPortNameOffset = (WORD)(ptd->tdDeviceNameOffset + nDeviceNameSize);
  1151.         ocscpy((LPOLESTR)((BYTE*)ptd + ptd->tdPortNameOffset), lpszPortNameOle);
  1152.         ptd->tdExtDevmodeOffset = (WORD)(ptd->tdPortNameOffset + nPortNameSize);
  1153.         memcpy((BYTE*)ptd + ptd->tdExtDevmodeOffset, lpDevModeOle,
  1154.             sizeof(DEVMODEOLE)+lpDevModeOle->dmDriverExtra);
  1155.     }
  1156.     return ptd;
  1157. }
  1158.  
  1159. DVTARGETDEVICE* AFXAPI _AfxOleCreateTargetDevice(LPPRINTDLG lpPrintDlg)
  1160. {
  1161.     DVTARGETDEVICE* ptd=NULL;
  1162.     LPDEVNAMES pDN;
  1163.     LPDEVMODE pDM;
  1164.  
  1165.     if ((pDN = (LPDEVNAMES)GlobalLock(lpPrintDlg->hDevNames)) == NULL)
  1166.         return NULL;
  1167.  
  1168.     if ((pDM = (LPDEVMODE)GlobalLock(lpPrintDlg->hDevMode)) == NULL)
  1169.     {
  1170.         GlobalUnlock(lpPrintDlg->hDevNames);
  1171.         return NULL;
  1172.     }
  1173.  
  1174.     ptd = _AfxOleCreateTargetDevice(pDN, pDM);
  1175.  
  1176.     GlobalUnlock(lpPrintDlg->hDevNames);
  1177.     GlobalUnlock(lpPrintDlg->hDevMode);
  1178.  
  1179.     return ptd;
  1180. }
  1181.  
  1182. LPMONIKER AFXAPI _AfxOleGetFirstMoniker(LPMONIKER lpmk)
  1183. {
  1184.     if (lpmk == NULL)
  1185.         return NULL;
  1186.  
  1187.     DWORD dwMksys;
  1188.     if (lpmk->IsSystemMoniker(&dwMksys) == S_OK
  1189.         && dwMksys == MKSYS_GENERICCOMPOSITE)
  1190.     {
  1191.         LPENUMMONIKER lpenumMoniker = NULL;
  1192.         SCODE sc = lpmk->Enum(TRUE, &lpenumMoniker);
  1193.         if (sc != S_OK)
  1194.             return NULL;
  1195.  
  1196.         ASSERT(lpenumMoniker != NULL);
  1197.         LPMONIKER lpmkFirst = NULL;
  1198.         sc = lpenumMoniker->Next(1, &lpmkFirst, NULL);
  1199.         RELEASE(lpenumMoniker);
  1200.         return lpmkFirst;
  1201.     }
  1202.  
  1203.     // otherwise -- return the moniker itself
  1204.     lpmk->AddRef();
  1205.     return lpmk;
  1206. }
  1207.  
  1208. DWORD AFXAPI _AfxOleGetLenFilePrefixOfMoniker(LPMONIKER lpmk)
  1209. {
  1210.     USES_CONVERSION;
  1211.  
  1212.     if (lpmk == NULL)
  1213.         return 0;
  1214.  
  1215.     DWORD nLen = 0;
  1216.     LPMONIKER lpmkFirst = _AfxOleGetFirstMoniker(lpmk);
  1217.     if (lpmkFirst != NULL)
  1218.     {
  1219.         DWORD  dwMksys;
  1220.         if (lpmkFirst->IsSystemMoniker(&dwMksys) == S_OK &&
  1221.             dwMksys == MKSYS_FILEMONIKER)
  1222.         {
  1223.             LPBC lpbc = NULL;
  1224.             SCODE sc = CreateBindCtx(0, &lpbc);
  1225.             if (sc == S_OK)
  1226.             {
  1227.                 LPOLESTR lpw = NULL;
  1228.                 sc = lpmkFirst->GetDisplayName(lpbc, NULL, &lpw);
  1229.                 LPTSTR lpsz = OLE2T(lpw);
  1230.                 if (sc == S_OK && lpsz != NULL)
  1231.                 {
  1232.                     nLen = lstrlen(lpsz);
  1233.                     CoTaskMemFree(lpw);
  1234.                 }
  1235.                 RELEASE(lpbc);
  1236.             }
  1237.         }
  1238.         RELEASE(lpmkFirst);
  1239.     }
  1240.     return nLen;
  1241. }
  1242.  
  1243. DVTARGETDEVICE* AFXAPI _AfxOleCopyTargetDevice(DVTARGETDEVICE* ptdSrc)
  1244. {
  1245.     if (ptdSrc == NULL)
  1246.         return NULL;
  1247.  
  1248.     DVTARGETDEVICE* ptdDest =
  1249.         (DVTARGETDEVICE*)CoTaskMemAlloc(ptdSrc->tdSize);
  1250.     if (ptdDest == NULL)
  1251.         return NULL;
  1252.  
  1253.     memcpy(ptdDest, ptdSrc, (size_t)ptdSrc->tdSize);
  1254.     return ptdDest;
  1255. }
  1256.  
  1257. void AFXAPI _AfxOleCopyFormatEtc(LPFORMATETC petcDest, LPFORMATETC petcSrc)
  1258. {
  1259.     ASSERT(petcDest != NULL);
  1260.     ASSERT(petcSrc != NULL);
  1261.  
  1262.     petcDest->cfFormat = petcSrc->cfFormat;
  1263.     petcDest->ptd = _AfxOleCopyTargetDevice(petcSrc->ptd);
  1264.     petcDest->dwAspect = petcSrc->dwAspect;
  1265.     petcDest->lindex = petcSrc->lindex;
  1266.     petcDest->tymed = petcSrc->tymed;
  1267. }
  1268.  
  1269. HDC WINAPI _AfxOleCreateDC(DVTARGETDEVICE* ptd)
  1270. {
  1271.     USES_CONVERSION;
  1272.  
  1273.     // return screen DC for NULL target device
  1274.     if (ptd == NULL)
  1275.         return ::CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
  1276.  
  1277.     LPDEVMODEOLE lpDevMode;
  1278.     LPOLESTR lpszDriverName;
  1279.     LPOLESTR lpszDeviceName;
  1280.     LPOLESTR lpszPortName;
  1281.  
  1282.     if (ptd->tdExtDevmodeOffset == 0)
  1283.         lpDevMode = NULL;
  1284.     else
  1285.         lpDevMode  = (LPDEVMODEOLE) ((LPSTR)ptd + ptd->tdExtDevmodeOffset);
  1286.  
  1287.     lpszDriverName = (LPOLESTR)((BYTE*)ptd + ptd->tdDriverNameOffset);
  1288.     lpszDeviceName = (LPOLESTR)((BYTE*)ptd + ptd->tdDeviceNameOffset);
  1289.     lpszPortName   = (LPOLESTR)((BYTE*)ptd + ptd->tdPortNameOffset);
  1290.  
  1291.     return ::CreateDC(OLE2CT(lpszDriverName), OLE2CT(lpszDeviceName),
  1292.         OLE2CT(lpszPortName), DEVMODEOLE2T(lpDevMode));
  1293. }
  1294.  
  1295. void AFXAPI _AfxDeleteMetafilePict(HGLOBAL hMetaPict)
  1296. {
  1297.     if (hMetaPict != NULL)
  1298.     {
  1299.         STGMEDIUM stgMedium;
  1300.         stgMedium.hGlobal = hMetaPict;
  1301.         stgMedium.tymed = TYMED_MFPICT;
  1302.         stgMedium.pUnkForRelease = NULL;
  1303.         ReleaseStgMedium(&stgMedium);
  1304.     }
  1305. }
  1306.  
  1307. #define HIMETRIC_PER_INCH   2540
  1308. #define MAP_PIX_TO_LOGHIM(x,ppli)   MulDiv(HIMETRIC_PER_INCH, (x), (ppli))
  1309. #define MAP_LOGHIM_TO_PIX(x,ppli)   MulDiv((ppli), (x), HIMETRIC_PER_INCH)
  1310.  
  1311. void AFXAPI _AfxXformSizeInPixelsToHimetric(
  1312.     HDC hDC, LPSIZEL lpSizeInPix, LPSIZEL lpSizeInHiMetric)
  1313. {
  1314.     int cxPPI;
  1315.     int cyPPI;
  1316.  
  1317.     if ((NULL == hDC) || (GetDeviceCaps(hDC, LOGPIXELSX) == 0))
  1318.     {
  1319.         cxPPI = afxData.cxPixelsPerInch;
  1320.         cyPPI = afxData.cyPixelsPerInch;
  1321.     }
  1322.     else
  1323.     {
  1324.         cxPPI = GetDeviceCaps(hDC, LOGPIXELSX);
  1325.         cyPPI = GetDeviceCaps(hDC, LOGPIXELSY);
  1326.     }
  1327.  
  1328.     lpSizeInHiMetric->cx = (long)MAP_PIX_TO_LOGHIM((int)lpSizeInPix->cx, cxPPI);
  1329.     lpSizeInHiMetric->cy = (long)MAP_PIX_TO_LOGHIM((int)lpSizeInPix->cy, cyPPI);
  1330. }
  1331.  
  1332. void AFXAPI _AfxXformSizeInHimetricToPixels(
  1333.     HDC hDC, LPSIZEL lpSizeInHiMetric, LPSIZEL lpSizeInPix)
  1334. {
  1335.     int cxPPI;
  1336.     int cyPPI;
  1337.  
  1338.     if ((NULL == hDC) || (GetDeviceCaps(hDC, LOGPIXELSX) == 0))
  1339.     {
  1340.         cxPPI = afxData.cxPixelsPerInch;
  1341.         cyPPI = afxData.cyPixelsPerInch;
  1342.     }
  1343.     else
  1344.     {
  1345.         cxPPI = GetDeviceCaps(hDC, LOGPIXELSX);
  1346.         cyPPI = GetDeviceCaps(hDC, LOGPIXELSY);
  1347.     }
  1348.  
  1349.     lpSizeInPix->cx = (long)MAP_LOGHIM_TO_PIX((int)lpSizeInHiMetric->cx, cxPPI);
  1350.     lpSizeInPix->cy = (long)MAP_LOGHIM_TO_PIX((int)lpSizeInHiMetric->cy, cyPPI);
  1351. }
  1352.  
  1353. #ifdef AFX_INIT_SEG
  1354. #pragma code_seg(AFX_INIT_SEG)
  1355. #endif
  1356.  
  1357. IMPLEMENT_DYNAMIC(COleException, CException)
  1358.  
  1359. /////////////////////////////////////////////////////////////////////////////
  1360.