home *** CD-ROM | disk | FTP | other *** search
/ Supercompiler 1997 / SUPERCOMPILER97.iso / MS_VC.50 / VC / MFC / SRC / OLEMISC.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-11-09  |  39.4 KB  |  1,366 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1997 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. #ifndef _MAC
  431.     LPTSTR lpBuffer;
  432.     if (::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
  433.                 FORMAT_MESSAGE_FROM_SYSTEM,
  434.                 NULL, m_sc,
  435.                 MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT),
  436.                 (LPTSTR) &lpBuffer, 0, NULL) == 0)
  437.     {
  438.         *lpszError = '\0';
  439.         return FALSE;
  440.     }
  441.     else
  442.     {
  443.         lstrcpyn(lpszError, lpBuffer, nMaxError);
  444.         LocalFree(lpBuffer);
  445.         return TRUE;
  446.     }
  447.  
  448. #else
  449.     UNUSED_ALWAYS(nMaxError);
  450.     *lpszError = '\0';
  451.     return FALSE;
  452. #endif // _MAC
  453. }
  454.  
  455. /////////////////////////////////////////////////////////////////////////////
  456. // Turn a caught exception into an OLE return code
  457.  
  458. SCODE PASCAL COleException::Process(const CException* pAnyException)
  459. {
  460.     SCODE sc;
  461.     if (pAnyException->IsKindOf(RUNTIME_CLASS(COleException)))
  462.         sc = ((COleException*)pAnyException)->m_sc;
  463.     else if (pAnyException->IsKindOf(RUNTIME_CLASS(CMemoryException)))
  464.         sc = E_OUTOFMEMORY;
  465.     else if (pAnyException->IsKindOf(RUNTIME_CLASS(CNotSupportedException)))
  466.         sc = E_NOTIMPL;
  467.     else
  468.         sc = E_UNEXPECTED;  // some other problem
  469.  
  470.     return sc;
  471. }
  472.  
  473. /////////////////////////////////////////////////////////////////////////////
  474. // Implementation helpers
  475.  
  476. HMENU AFXAPI AfxMergeMenus(HMENU hMenuShared, HMENU hMenuSource,
  477.     LONG* lpMenuWidths, int iWidthIndex, BOOL bMergeHelpMenus /* = FALSE */)
  478. {
  479.     ASSERT(hMenuShared != NULL && IsMenu(hMenuShared));
  480.     ASSERT(hMenuSource != NULL && IsMenu(hMenuSource));
  481.  
  482.     BOOL bHelpMergedAsSubMenu = FALSE;
  483.     HMENU hHelpSubMenu = NULL;
  484.  
  485.     // copy the popups from the pMenuSource
  486.     int cMenuItems = GetMenuItemCount(hMenuSource);
  487.     int cGroupWidth = 0;
  488.     int nPosition = 0;
  489.  
  490.     // insert at appropriate spot depending on iWidthIndex
  491.     ASSERT(iWidthIndex == 0 || iWidthIndex == 1);
  492.     if (iWidthIndex == 1)
  493.         nPosition = (int)lpMenuWidths[0];
  494.  
  495.     for (int i = 0; i < cMenuItems; i++)
  496.     {
  497.         // get the HMENU of the popup
  498.         HMENU hMenuPopup = ::GetSubMenu(hMenuSource, i);
  499.  
  500.         // separators move us to next group
  501.         UINT state = GetMenuState(hMenuSource, i, MF_BYPOSITION);
  502.         if (hMenuPopup == NULL && (state & MF_SEPARATOR) != 0)
  503.         {
  504.             ASSERT(iWidthIndex <= 5);   // servers should not touch past 5
  505.             lpMenuWidths[iWidthIndex] = cGroupWidth;
  506.             cGroupWidth = 0;
  507.             if (iWidthIndex < 5)
  508.                 nPosition += (int)lpMenuWidths[iWidthIndex+1];
  509.             iWidthIndex += 2;
  510.         }
  511.         else
  512.         {
  513.             HMENU hHelpMenu = NULL;
  514.  
  515.             // are we processing the help menu group?
  516.  
  517.             if (bMergeHelpMenus && iWidthIndex == 5)
  518.             {
  519.                 // if so, see if the container has Help any menu items
  520.                 if (lpMenuWidths[iWidthIndex] == 1)
  521.                 {
  522.                     // get the help menu from the container
  523.                     hHelpMenu = GetSubMenu(hMenuShared, nPosition);
  524.                 }
  525.             }
  526.  
  527.             // get the menu item text
  528.             TCHAR szItemText[256];
  529.             int nLen = GetMenuString(hMenuSource, i, szItemText,
  530.                 sizeof szItemText, MF_BYPOSITION);
  531.  
  532.             // popups are handled differently than normal menu items
  533.             if (hMenuPopup != NULL)
  534.             {
  535.                 if (hHelpMenu != NULL)
  536.                 {
  537.                     CString strTearOff = AfxGetAppName();
  538.                     if (!strTearOff.IsEmpty())
  539.                         strTearOff += ' ';
  540.                     strTearOff += szItemText;
  541.  
  542.                     // container has help items -- add ours to its submenu
  543.                     AppendMenu(hHelpMenu, MF_STRING | MF_POPUP,
  544.                         (UINT)hMenuPopup, strTearOff);
  545.  
  546.                     // clear the count of Help group items and add
  547.                     // the help menu to the window group
  548.  
  549.                     lpMenuWidths[iWidthIndex] = 0;
  550.                     lpMenuWidths[iWidthIndex-1]++;
  551.  
  552.                     bHelpMergedAsSubMenu = TRUE;
  553.                 }
  554.                 else if (::GetMenuItemCount(hMenuPopup) != 0)
  555.                 {
  556.                     // strip the HIBYTE because it contains a count of items
  557.                     state = LOBYTE(state) | MF_POPUP;   // must be popup
  558.  
  559.                     // non-empty popup -- add it to the shared menu bar
  560.                     InsertMenu(hMenuShared, nPosition, state | MF_BYPOSITION,
  561.                         (UINT)hMenuPopup, szItemText);
  562.                     ++nPosition;
  563.                     ++cGroupWidth;
  564.                 }
  565.             }
  566.             else if (nLen > 0)
  567.             {
  568.                 // only non-empty items are added
  569.                 ASSERT(szItemText[0] != 0);
  570.  
  571.                 // here the state does not contain a count in the HIBYTE
  572.                 InsertMenu(hMenuShared, nPosition, state | MF_BYPOSITION,
  573.                     GetMenuItemID(hMenuSource, i), szItemText);
  574.                 ++nPosition;
  575.                 ++cGroupWidth;
  576.             }
  577.         }
  578.     }
  579.  
  580.     // set the last group width
  581.  
  582.     if (!bHelpMergedAsSubMenu)
  583.     {
  584.         ASSERT(iWidthIndex <= 5);   // servers should not touch past 5
  585.         lpMenuWidths[iWidthIndex] = cGroupWidth;
  586.     }
  587.  
  588.     return hHelpSubMenu;
  589. }
  590.  
  591. void AFXAPI AfxUnmergeMenus(HMENU hMenuShared, HMENU hMenuSource,
  592.     HMENU hHelpMenuPopup /* = NULL */)
  593. {
  594.     ASSERT(hMenuShared != NULL && IsMenu(hMenuShared));
  595.     ASSERT(hMenuSource != NULL && IsMenu(hMenuSource));
  596.     ASSERT(hHelpMenuPopup == NULL || IsMenu(hHelpMenuPopup));
  597.  
  598.     int cOurItems = GetMenuItemCount(hMenuSource);
  599.     int cMenuItems = GetMenuItemCount(hMenuShared);
  600.  
  601.     for (int i = cMenuItems-1; i >= 0; i--)
  602.     {
  603.         // check out the popup menus
  604.         HMENU hMenuPopup = ::GetSubMenu(hMenuShared, i);
  605.         if (hMenuPopup != NULL)
  606.         {
  607.             // if we have a Help submenu, check to see if it appears in this
  608.             // submenu someplace... this normally happens only in
  609.             // DocObject frame windows
  610.  
  611.             if (hHelpMenuPopup != NULL)
  612.             {
  613.                 int cPopupItems = ::GetMenuItemCount(hMenuPopup);
  614.                 for (int k = 0; k < cPopupItems; k++)
  615.                 {
  616.                     if (::GetSubMenu(hMenuPopup, k) == hHelpMenuPopup)
  617.                     {
  618.                         ::RemoveMenu(hMenuPopup, k, MF_BYPOSITION);
  619.                         hHelpMenuPopup = NULL;  // can only have one
  620.                         break;
  621.                     }
  622.                 }
  623.             }
  624.             else
  625.             {
  626.                 // if it is one of ours, remove it from the pMenuShared
  627.                 for (int j = 0; j < cOurItems; j++)
  628.                 {
  629.                     if (::GetSubMenu(hMenuSource, j) == hMenuPopup)
  630.                     {
  631.                         // remove the menu from pMenuShared
  632.                         RemoveMenu(hMenuShared, i, MF_BYPOSITION);
  633.                         break;
  634.                     }
  635.                 }
  636.             }
  637.         }
  638.     }
  639. }
  640.  
  641. // Helper for creating default FORMATETC from cfFormat
  642. LPFORMATETC AFXAPI _AfxFillFormatEtc(
  643.     LPFORMATETC lpFormatEtc, CLIPFORMAT cfFormat, LPFORMATETC lpFormatEtcFill)
  644. {
  645.     ASSERT(lpFormatEtcFill != NULL);
  646.     if (lpFormatEtc == NULL && cfFormat != 0)
  647.     {
  648.         lpFormatEtc = lpFormatEtcFill;
  649.         lpFormatEtc->cfFormat = cfFormat;
  650.         lpFormatEtc->ptd = NULL;
  651.         lpFormatEtc->dwAspect = DVASPECT_CONTENT;
  652.         lpFormatEtc->lindex = -1;
  653.         lpFormatEtc->tymed = (DWORD) -1;
  654.     }
  655.     return lpFormatEtc;
  656. }
  657.  
  658. static HGLOBAL AFXAPI CopyGlobalMemory(HGLOBAL hDest, HGLOBAL hSource)
  659. {
  660.     ASSERT(hSource != NULL);
  661.  
  662.     // make sure we have suitable hDest
  663.     DWORD nSize = ::GlobalSize(hSource);
  664.     if (hDest == NULL)
  665.     {
  666.         hDest = ::GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, nSize);
  667.         if (hDest == NULL)
  668.             return NULL;
  669.     }
  670.     else if (nSize > ::GlobalSize(hDest))
  671.     {
  672.         // hDest is not large enough
  673.         return NULL;
  674.     }
  675.  
  676.     // copy the bits
  677.     LPVOID lpSource = ::GlobalLock(hSource);
  678.     LPVOID lpDest = ::GlobalLock(hDest);
  679.     ASSERT(lpDest != NULL);
  680.     ASSERT(lpSource != NULL);
  681.     memcpy(lpDest, lpSource, nSize);
  682.     ::GlobalUnlock(hDest);
  683.     ::GlobalUnlock(hSource);
  684.  
  685.     // success -- return hDest
  686.     return hDest;
  687. }
  688.  
  689. BOOL AFXAPI _AfxCopyStgMedium(
  690.     CLIPFORMAT cfFormat, LPSTGMEDIUM lpDest, LPSTGMEDIUM lpSource)
  691. {
  692.     if (lpDest->tymed == TYMED_NULL)
  693.     {
  694.         ASSERT(lpSource->tymed != TYMED_NULL);
  695.         switch (lpSource->tymed)
  696.         {
  697.         case TYMED_ENHMF:
  698.         case TYMED_HGLOBAL:
  699.             ASSERT(sizeof(HGLOBAL) == sizeof(HENHMETAFILE));
  700.             lpDest->tymed = lpSource->tymed;
  701.             lpDest->hGlobal = NULL;
  702.             break;  // fall through to CopyGlobalMemory case
  703.  
  704.         case TYMED_ISTREAM:
  705.             lpDest->pstm = lpSource->pstm;
  706.             lpDest->pstm->AddRef();
  707.             lpDest->tymed = TYMED_ISTREAM;
  708.             return TRUE;
  709.  
  710.         case TYMED_ISTORAGE:
  711.             lpDest->pstg = lpSource->pstg;
  712.             lpDest->pstg->AddRef();
  713.             lpDest->tymed = TYMED_ISTORAGE;
  714.             return TRUE;
  715.  
  716.         case TYMED_MFPICT:
  717.             {
  718.                 // copy LPMETAFILEPICT struct + embedded HMETAFILE
  719.                 HGLOBAL hDest = ::CopyGlobalMemory(NULL, lpSource->hGlobal);
  720.                 if (hDest == NULL)
  721.                     return FALSE;
  722.                 LPMETAFILEPICT lpPict = (LPMETAFILEPICT)::GlobalLock(hDest);
  723.                 ASSERT(lpPict != NULL);
  724.                 lpPict->hMF = ::CopyMetaFile(lpPict->hMF, NULL);
  725.                 if (lpPict->hMF == NULL)
  726.                 {
  727.                     ::GlobalUnlock(hDest);
  728.                     ::GlobalFree(hDest);
  729.                     return FALSE;
  730.                 }
  731.                 ::GlobalUnlock(hDest);
  732.  
  733.                 // fill STGMEDIUM struct
  734.                 lpDest->hGlobal = hDest;
  735.                 lpDest->tymed = TYMED_MFPICT;
  736.             }
  737.             return TRUE;
  738.  
  739.         case TYMED_GDI:
  740.             lpDest->tymed = TYMED_GDI;
  741.             lpDest->hGlobal = NULL;
  742.             break;
  743.  
  744.         case TYMED_FILE:
  745.             {
  746.                 USES_CONVERSION;
  747.                 lpDest->tymed = TYMED_FILE;
  748.                 ASSERT(lpSource->lpszFileName != NULL);
  749.                 UINT cbSrc = ocslen(lpSource->lpszFileName);
  750.                 LPOLESTR szFileName = (LPOLESTR)CoTaskMemAlloc(cbSrc*sizeof(OLECHAR));
  751.                 lpDest->lpszFileName = szFileName;
  752.                 if (szFileName == NULL)
  753.                     return FALSE;
  754.                 memcpy(szFileName, lpSource->lpszFileName,  (cbSrc+1)*sizeof(OLECHAR));
  755.                 return TRUE;
  756.             }
  757.  
  758.         // unable to create + copy other TYMEDs
  759.         default:
  760.             return FALSE;
  761.         }
  762.     }
  763.     ASSERT(lpDest->tymed == lpSource->tymed);
  764.  
  765.     switch (lpSource->tymed)
  766.     {
  767.     case TYMED_HGLOBAL:
  768.         {
  769.             HGLOBAL hDest = ::CopyGlobalMemory(lpDest->hGlobal,
  770.                 lpSource->hGlobal);
  771.             if (hDest == NULL)
  772.                 return FALSE;
  773.  
  774.             lpDest->hGlobal = hDest;
  775.         }
  776.         return TRUE;
  777.  
  778.     case TYMED_ISTREAM:
  779.         {
  780.             ASSERT(lpDest->pstm != NULL);
  781.             ASSERT(lpSource->pstm != NULL);
  782.  
  783.             // get the size of the source stream
  784.             STATSTG stat;
  785.             if (lpSource->pstm->Stat(&stat, STATFLAG_NONAME) != S_OK)
  786.             {
  787.                 // unable to get size of source stream
  788.                 return FALSE;
  789.             }
  790.             ASSERT(stat.pwcsName == NULL);
  791.  
  792.             // always seek to zero before copy
  793.             LARGE_INTEGER zero = { 0, 0 };
  794.             lpDest->pstm->Seek(zero, STREAM_SEEK_SET, NULL);
  795.             lpSource->pstm->Seek(zero, STREAM_SEEK_SET, NULL);
  796.  
  797.             // copy source to destination
  798.             if (lpSource->pstm->CopyTo(lpDest->pstm, stat.cbSize,
  799.                 NULL, NULL) != NULL)
  800.             {
  801.                 // copy from source to dest failed
  802.                 return FALSE;
  803.             }
  804.  
  805.             // always seek to zero after copy
  806.             lpDest->pstm->Seek(zero, STREAM_SEEK_SET, NULL);
  807.             lpSource->pstm->Seek(zero, STREAM_SEEK_SET, NULL);
  808.         }
  809.         return TRUE;
  810.  
  811.     case TYMED_ISTORAGE:
  812.         {
  813.             ASSERT(lpDest->pstg != NULL);
  814.             ASSERT(lpSource->pstg != NULL);
  815.  
  816.             // just copy source to destination
  817.             if (lpSource->pstg->CopyTo(0, NULL, NULL, lpDest->pstg) != S_OK)
  818.                 return FALSE;
  819.         }
  820.         return TRUE;
  821.  
  822.     case TYMED_FILE:
  823.         {
  824.             USES_CONVERSION;
  825.             ASSERT(lpSource->lpszFileName != NULL);
  826.             ASSERT(lpDest->lpszFileName != NULL);
  827.             return CopyFile(OLE2T(lpSource->lpszFileName), OLE2T(lpDest->lpszFileName), FALSE);
  828.         }
  829.  
  830.  
  831.     case TYMED_ENHMF:
  832.     case TYMED_GDI:
  833.         {
  834.             ASSERT(sizeof(HGLOBAL) == sizeof(HENHMETAFILE));
  835.  
  836.             // with TYMED_GDI cannot copy into existing HANDLE
  837.             if (lpDest->hGlobal != NULL)
  838.                 return FALSE;
  839.  
  840.             // otherwise, use OleDuplicateData for the copy
  841.             lpDest->hGlobal = OleDuplicateData(lpSource->hGlobal, cfFormat, 0);
  842.             if (lpDest->hGlobal == NULL)
  843.                 return FALSE;
  844.         }
  845.         return TRUE;
  846.  
  847.     // other TYMEDs cannot be copied
  848.     default:
  849.         return FALSE;
  850.     }
  851. }
  852.  
  853. /////////////////////////////////////////////////////////////////////////////
  854. // OLE utility functions (some borrowed from OLE2UI library)
  855.  
  856. HGLOBAL AFXAPI _AfxOleGetObjectDescriptorData(
  857.     CLSID       clsid,
  858.     DWORD       dwDrawAspect,
  859.     SIZEL       sizel,
  860.     POINTL      pointl,
  861.     DWORD       dwStatus,
  862.     LPCOLESTR   lpszFullUserTypeName,
  863.     LPCOLESTR   lpszSrcOfCopy)
  864. {
  865.     HGLOBAL     hMem = NULL;
  866.     LPOBJECTDESCRIPTOR lpOD;
  867.     DWORD       dwObjectDescSize, dwFullUserTypeNameLen, dwSrcOfCopyLen;
  868.  
  869.     // Get the length of Full User Type Name; Add 1 for the null terminator
  870.     dwFullUserTypeNameLen = lpszFullUserTypeName ?
  871.         ocslen(lpszFullUserTypeName)+1 : 0;
  872.  
  873.     // Get the Source of Copy string and it's length;
  874.     //  Add 1 for the null terminator
  875.     if (lpszSrcOfCopy && lpszSrcOfCopy[0] != '\0')
  876.        dwSrcOfCopyLen = ocslen(lpszSrcOfCopy)+1;
  877.     else
  878.     {
  879.        // No src moniker so use user type name as source string.
  880.        lpszSrcOfCopy =  lpszFullUserTypeName;
  881.        dwSrcOfCopyLen = dwFullUserTypeNameLen;
  882.     }
  883.  
  884.     // Allocate space for OBJECTDESCRIPTOR and the additional string data
  885.     dwObjectDescSize = sizeof(OBJECTDESCRIPTOR);
  886.     hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE | GMEM_ZEROINIT,
  887.        dwObjectDescSize + (dwFullUserTypeNameLen + dwSrcOfCopyLen) *
  888.         sizeof(OLECHAR));
  889.     if (!hMem)
  890.         return NULL;
  891.  
  892.     lpOD = (LPOBJECTDESCRIPTOR)GlobalLock(hMem);
  893.  
  894.     // Set the FullUserTypeName offset and copy the string
  895.     if (lpszFullUserTypeName)
  896.     {
  897.         lpOD->dwFullUserTypeName = dwObjectDescSize;
  898.         ocscpy((LPOLESTR)((LPBYTE)lpOD+lpOD->dwFullUserTypeName), lpszFullUserTypeName);
  899.     }
  900.     else
  901.         lpOD->dwFullUserTypeName = 0;  // zero offset indicates that string is not present
  902.  
  903.     // Set the SrcOfCopy offset and copy the string
  904.     if (lpszSrcOfCopy)
  905.     {
  906.         lpOD->dwSrcOfCopy = dwObjectDescSize + dwFullUserTypeNameLen * sizeof(OLECHAR);
  907.         ocscpy((LPOLESTR)((LPBYTE)lpOD+lpOD->dwSrcOfCopy), lpszSrcOfCopy);
  908.     }
  909.     else
  910.         lpOD->dwSrcOfCopy = 0;  // zero offset indicates that string is not present
  911.  
  912.     // Initialize the rest of the OBJECTDESCRIPTOR
  913.     lpOD->cbSize       = dwObjectDescSize +
  914.         (dwFullUserTypeNameLen + dwSrcOfCopyLen) * sizeof(OLECHAR);
  915.     lpOD->clsid        = clsid;
  916.     lpOD->dwDrawAspect = dwDrawAspect;
  917.     lpOD->sizel        = sizel;
  918.     lpOD->pointl       = pointl;
  919.     lpOD->dwStatus     = dwStatus;
  920.  
  921.     GlobalUnlock(hMem);
  922.     return hMem;
  923. }
  924.  
  925. HGLOBAL AFXAPI _AfxOleGetObjectDescriptorData(
  926.     LPOLEOBJECT     lpOleObj,
  927.     LPCOLESTR       lpszSrcOfCopy,
  928.     DWORD           dwDrawAspect,
  929.     POINTL          pointl,
  930.     LPSIZEL         lpSizelHim)
  931. {
  932.     USES_CONVERSION;
  933.  
  934.     CLSID           clsid;
  935.     LPOLESTR        lpszFullUserTypeName = NULL;
  936.     LPMONIKER       lpSrcMonikerOfCopy = NULL;
  937.     HGLOBAL         hObjDesc = NULL;
  938.     IBindCtx        *pbc = NULL;
  939.     SCODE           sc;
  940.     SIZEL           sizelHim;
  941.     BOOL            bFreeSrcOfCopy = FALSE;
  942.     LPVIEWOBJECT2   lpViewObj2;
  943.     LPOLELINK       lpOleLink;
  944.     BOOL            fIsLink;
  945.     TCHAR           szLinkedTypeFmt[80];
  946.     LPCOLESTR       lpszLinkedTypeFmt;
  947.     LPOLESTR        lpszBuf = NULL;
  948.     DWORD           dwStatus = 0;
  949.  
  950.     // query for IOleLink
  951.     lpOleLink = QUERYINTERFACE(lpOleObj, IOleLink);
  952.     fIsLink = (lpOleLink ? TRUE : FALSE);
  953.  
  954.     // query for IViewObject2
  955.     lpViewObj2 = QUERYINTERFACE(lpOleObj, IViewObject2);
  956.  
  957.     // Get CLSID
  958.     sc = lpOleObj->GetUserClassID(&clsid);
  959.     if (sc != S_OK)
  960.         clsid = CLSID_NULL;
  961.  
  962.     // Get FullUserTypeName
  963.     sc = lpOleObj->GetUserType(USERCLASSTYPE_FULL, &lpszFullUserTypeName);
  964.  
  965.     // if object is a link, then expand usertypename to be "Linked %s"
  966.     if (fIsLink && lpszFullUserTypeName != NULL)
  967.     {
  968.         // Note: If this LoadString call fails, it is likely that
  969.         //  _AFX_NO_OLE_RESOURCES is defined in your .RC file.
  970.         // To correct the situation remove the following line from your
  971.         //  resource script:
  972.         //      #define _AFX_NO_OLE_RESOURCES
  973.         // This should be done using the Resource.Set Includes... command.
  974.  
  975.         VERIFY(AfxLoadString(AFX_IDS_PASTELINKEDTYPE, szLinkedTypeFmt));
  976.         lpszLinkedTypeFmt = T2COLE(szLinkedTypeFmt);
  977.         lpszBuf = (LPOLESTR)CoTaskMemAlloc((ocslen(lpszFullUserTypeName) +
  978.             ocslen(lpszLinkedTypeFmt) + 1) * sizeof(OLECHAR));
  979.         if (lpszBuf != NULL)
  980.         {
  981. #ifdef OLE2ANSI
  982.             sprintf(lpszBuf, lpszLinkedTypeFmt, lpszFullUserTypeName);
  983. #else
  984.             swprintf(lpszBuf, lpszLinkedTypeFmt, lpszFullUserTypeName);
  985. #endif
  986.             CoTaskMemFree(lpszFullUserTypeName);
  987.             lpszFullUserTypeName = lpszBuf;
  988.         }
  989.     }
  990.  
  991.     // get source of copy
  992.     if (fIsLink)
  993.     {
  994.         sc = lpOleLink->GetSourceDisplayName((LPOLESTR*)&lpszSrcOfCopy);
  995.         bFreeSrcOfCopy = TRUE;
  996.     }
  997.     else if (lpszSrcOfCopy == NULL)
  998.     {
  999.         sc = lpOleObj->GetMoniker(
  1000.             OLEGETMONIKER_TEMPFORUSER, OLEWHICHMK_OBJFULL, &lpSrcMonikerOfCopy);
  1001.         if (sc == S_OK)
  1002.         {
  1003.             CreateBindCtx(0, &pbc);
  1004.             lpSrcMonikerOfCopy->GetDisplayName(pbc, NULL,
  1005.                 (LPOLESTR*)&lpszSrcOfCopy);
  1006.             RELEASE(pbc);
  1007.             bFreeSrcOfCopy = TRUE;
  1008.         }
  1009.     }
  1010.  
  1011.     if (lpSizelHim)
  1012.     {
  1013.         // Use extents passed by the caller
  1014.         sizelHim = *lpSizelHim;
  1015.     }
  1016.     else if (lpViewObj2)
  1017.     {
  1018.         // Get the current extents from the object
  1019.         sc = lpViewObj2->GetExtent(dwDrawAspect, -1, NULL,
  1020.             (LPSIZEL)&sizelHim);
  1021.         if (sc != S_OK)
  1022.             sizelHim.cx = sizelHim.cy = 0;
  1023.     }
  1024.     else
  1025.     {
  1026.         sizelHim.cx = sizelHim.cy = 0;
  1027.     }
  1028.  
  1029.     // Get dwStatus
  1030.     sc = lpOleObj->GetMiscStatus(dwDrawAspect, &dwStatus);
  1031.     if (sc != S_OK)
  1032.         dwStatus = 0;
  1033.  
  1034.     // Get OBJECTDESCRIPTOR
  1035.     hObjDesc = _AfxOleGetObjectDescriptorData(clsid, dwDrawAspect, sizelHim,
  1036.         pointl, dwStatus, lpszFullUserTypeName, lpszSrcOfCopy);
  1037.  
  1038.     // Clean up
  1039.     CoTaskMemFree(lpszFullUserTypeName);
  1040.     if (bFreeSrcOfCopy)
  1041.         CoTaskMemFree((LPOLESTR)lpszSrcOfCopy);
  1042.     RELEASE(lpSrcMonikerOfCopy);
  1043.     RELEASE(lpOleLink);
  1044.     RELEASE(lpViewObj2);
  1045.  
  1046.     return hObjDesc;
  1047. }
  1048.  
  1049. SCODE AFXAPI _AfxOleDoConvert(LPSTORAGE lpStg, REFCLSID rClsidNew)
  1050. {
  1051.     SCODE sc;
  1052.     CLSID clsidOld;
  1053.     if ((sc = ReadClassStg(lpStg, &clsidOld)) != S_OK)
  1054.     {
  1055.         clsidOld = CLSID_NULL;
  1056.         return sc;
  1057.     }
  1058.  
  1059.     // read old fmt/old user type; sets out params to NULL on error
  1060.     CLIPFORMAT cfOld;
  1061.     LPOLESTR lpszOld = NULL;
  1062.     sc = ReadFmtUserTypeStg(lpStg, &cfOld, &lpszOld);
  1063.     ASSERT(sc == S_OK || (cfOld == 0 && lpszOld == NULL));
  1064.  
  1065.     // get new user type name; if error, set to NULL string
  1066.     OLECHAR chZero = 0;
  1067.     LPOLESTR lpszNew = NULL;
  1068.     if (OleRegGetUserType(rClsidNew, USERCLASSTYPE_FULL, &lpszNew) != S_OK)
  1069.         lpszNew = &chZero;
  1070.  
  1071.     // write class stg
  1072.     if ((sc = WriteClassStg(lpStg, rClsidNew)) != S_OK)
  1073.         goto ErrorReturn;
  1074.  
  1075.     // write old fmt/new user type;
  1076.     if ((sc = WriteFmtUserTypeStg(lpStg, cfOld, lpszNew)) != S_OK)
  1077.         goto RewriteInfo;
  1078.  
  1079.     // set convert bit
  1080.     if ((sc = SetConvertStg(lpStg, TRUE)) != S_OK)
  1081.         goto RewriteInfo;
  1082.  
  1083.     goto ErrorReturn;
  1084.  
  1085. RewriteInfo:
  1086.     WriteClassStg(lpStg, clsidOld);
  1087.     WriteFmtUserTypeStg(lpStg, cfOld, lpszOld);
  1088.  
  1089. ErrorReturn:
  1090.     if (lpszNew != &chZero)
  1091.         CoTaskMemFree(lpszNew);
  1092.  
  1093.     CoTaskMemFree(lpszOld);
  1094.     return sc;
  1095. }
  1096.  
  1097. SCODE AFXAPI _AfxOleDoTreatAsClass(
  1098.     LPCTSTR lpszUserType, REFCLSID rclsid, REFCLSID rclsidNew)
  1099. {
  1100.     LPTSTR  lpszCLSID = NULL;
  1101.     HKEY    hKey;
  1102.  
  1103.     SCODE sc = CoTreatAsClass(rclsid, rclsidNew);
  1104.     if (sc != S_OK && lpszUserType != NULL)
  1105.     {
  1106.         RegOpenKey(HKEY_CLASSES_ROOT, _T("CLSID"), &hKey);
  1107.         LPOLESTR lpOleStr = NULL;
  1108.         StringFromCLSID(rclsid, &lpOleStr);
  1109.         lpszCLSID = TASKSTRINGOLE2T(lpOleStr);
  1110.         RegSetValue(hKey, lpszCLSID, REG_SZ, lpszUserType,
  1111.             lstrlen(lpszUserType) * sizeof(TCHAR));
  1112.  
  1113.         CoTaskMemFree(lpszCLSID);
  1114.         sc = CoTreatAsClass(rclsid, rclsidNew);
  1115.         RegCloseKey(hKey);
  1116.     }
  1117.     return sc;
  1118. }
  1119.  
  1120. #define DEVNAMEPART(pdn, x) (pdn->x == 0 ? NULL : (LPCTSTR)pdn + pdn->x)
  1121.  
  1122. DVTARGETDEVICE* AFXAPI _AfxOleCreateTargetDevice(LPDEVNAMES pDN, LPDEVMODE pDM)
  1123. {
  1124.     USES_CONVERSION;
  1125.  
  1126.     DVTARGETDEVICE* ptd = NULL;
  1127.     DWORD dwDevNamesSize, dwDevModeSize, dwPtdSize;
  1128.  
  1129.     LPCTSTR lpszDriverName = DEVNAMEPART(pDN, wDriverOffset);
  1130.     LPCTSTR lpszDeviceName = DEVNAMEPART(pDN, wDeviceOffset);
  1131.     LPCTSTR lpszPortName = DEVNAMEPART(pDN, wOutputOffset);
  1132.  
  1133.     LPCOLESTR lpszDriverNameOle = T2COLE(lpszDriverName);
  1134.     LPCOLESTR lpszDeviceNameOle = T2COLE(lpszDeviceName);
  1135.     LPCOLESTR lpszPortNameOle = T2COLE(lpszPortName);
  1136.     int nDriverNameSize = (lpszDriverNameOle == NULL) ? 0 : (ocslen(lpszDriverNameOle)+1)*sizeof(OLECHAR);
  1137.     int nDeviceNameSize = (lpszDeviceNameOle == NULL) ? 0 : (ocslen(lpszDeviceNameOle)+1)*sizeof(OLECHAR);
  1138.     int nPortNameSize = (lpszPortNameOle == NULL) ? 0 : (ocslen(lpszPortNameOle)+1)*sizeof(OLECHAR);
  1139.  
  1140.     LPDEVMODEOLE lpDevModeOle = DEVMODET2OLE(pDM);
  1141.  
  1142.     dwDevNamesSize = nDriverNameSize + nDeviceNameSize + nPortNameSize;
  1143.     dwDevModeSize = (DWORD)(lpDevModeOle->dmSize + lpDevModeOle->dmDriverExtra);
  1144.  
  1145.     dwPtdSize = sizeof(DVTARGETDEVICE) + dwDevNamesSize + dwDevModeSize;
  1146.  
  1147.     if ((ptd = (DVTARGETDEVICE*)CoTaskMemAlloc(dwPtdSize)) != NULL)
  1148.     {
  1149.         // copy in the info
  1150.         ptd->tdSize = (UINT)dwPtdSize;
  1151.  
  1152.         ptd->tdDriverNameOffset = sizeof(DVTARGETDEVICE);
  1153.         ocscpy((LPOLESTR)((BYTE*)ptd + ptd->tdDriverNameOffset), lpszDriverNameOle);
  1154.         ptd->tdDeviceNameOffset = (WORD)(ptd->tdDriverNameOffset + nDriverNameSize);
  1155.         ocscpy((LPOLESTR)((BYTE*)ptd + ptd->tdDeviceNameOffset), lpszDeviceNameOle);
  1156.         ptd->tdPortNameOffset = (WORD)(ptd->tdDeviceNameOffset + nDeviceNameSize);
  1157.         ocscpy((LPOLESTR)((BYTE*)ptd + ptd->tdPortNameOffset), lpszPortNameOle);
  1158.         ptd->tdExtDevmodeOffset = (WORD)(ptd->tdPortNameOffset + nPortNameSize);
  1159.         memcpy((BYTE*)ptd + ptd->tdExtDevmodeOffset, lpDevModeOle,
  1160.             sizeof(DEVMODEOLE)+lpDevModeOle->dmDriverExtra);
  1161.     }
  1162.     return ptd;
  1163. }
  1164.  
  1165. DVTARGETDEVICE* AFXAPI _AfxOleCreateTargetDevice(LPPRINTDLG lpPrintDlg)
  1166. {
  1167.     DVTARGETDEVICE* ptd=NULL;
  1168.     LPDEVNAMES pDN;
  1169.     LPDEVMODE pDM;
  1170.  
  1171.     if ((pDN = (LPDEVNAMES)GlobalLock(lpPrintDlg->hDevNames)) == NULL)
  1172.         return NULL;
  1173.  
  1174.     if ((pDM = (LPDEVMODE)GlobalLock(lpPrintDlg->hDevMode)) == NULL)
  1175.     {
  1176.         GlobalUnlock(lpPrintDlg->hDevNames);
  1177.         return NULL;
  1178.     }
  1179.  
  1180.     ptd = _AfxOleCreateTargetDevice(pDN, pDM);
  1181.  
  1182.     GlobalUnlock(lpPrintDlg->hDevNames);
  1183.     GlobalUnlock(lpPrintDlg->hDevMode);
  1184.  
  1185.     return ptd;
  1186. }
  1187.  
  1188. LPMONIKER AFXAPI _AfxOleGetFirstMoniker(LPMONIKER lpmk)
  1189. {
  1190.     if (lpmk == NULL)
  1191.         return NULL;
  1192.  
  1193.     DWORD dwMksys;
  1194.     if (lpmk->IsSystemMoniker(&dwMksys) == S_OK
  1195.         && dwMksys == MKSYS_GENERICCOMPOSITE)
  1196.     {
  1197.         LPENUMMONIKER lpenumMoniker = NULL;
  1198.         SCODE sc = lpmk->Enum(TRUE, &lpenumMoniker);
  1199.         if (sc != S_OK)
  1200.             return NULL;
  1201.  
  1202.         ASSERT(lpenumMoniker != NULL);
  1203.         LPMONIKER lpmkFirst = NULL;
  1204.         sc = lpenumMoniker->Next(1, &lpmkFirst, NULL);
  1205.         RELEASE(lpenumMoniker);
  1206.         return lpmkFirst;
  1207.     }
  1208.  
  1209.     // otherwise -- return the moniker itself
  1210.     lpmk->AddRef();
  1211.     return lpmk;
  1212. }
  1213.  
  1214. DWORD AFXAPI _AfxOleGetLenFilePrefixOfMoniker(LPMONIKER lpmk)
  1215. {
  1216.     USES_CONVERSION;
  1217.  
  1218.     if (lpmk == NULL)
  1219.         return 0;
  1220.  
  1221.     DWORD nLen = 0;
  1222.     LPMONIKER lpmkFirst = _AfxOleGetFirstMoniker(lpmk);
  1223.     if (lpmkFirst != NULL)
  1224.     {
  1225.         DWORD  dwMksys;
  1226.         if (lpmkFirst->IsSystemMoniker(&dwMksys) == S_OK &&
  1227.             dwMksys == MKSYS_FILEMONIKER)
  1228.         {
  1229.             LPBC lpbc = NULL;
  1230.             SCODE sc = CreateBindCtx(0, &lpbc);
  1231.             if (sc == S_OK)
  1232.             {
  1233.                 LPOLESTR lpw = NULL;
  1234.                 sc = lpmkFirst->GetDisplayName(lpbc, NULL, &lpw);
  1235.                 LPTSTR lpsz = OLE2T(lpw);
  1236.                 if (sc == S_OK && lpsz != NULL)
  1237.                 {
  1238.                     nLen = lstrlen(lpsz);
  1239.                     CoTaskMemFree(lpw);
  1240.                 }
  1241.                 RELEASE(lpbc);
  1242.             }
  1243.         }
  1244.         RELEASE(lpmkFirst);
  1245.     }
  1246.     return nLen;
  1247. }
  1248.  
  1249. DVTARGETDEVICE* AFXAPI _AfxOleCopyTargetDevice(DVTARGETDEVICE* ptdSrc)
  1250. {
  1251.     if (ptdSrc == NULL)
  1252.         return NULL;
  1253.  
  1254.     DVTARGETDEVICE* ptdDest =
  1255.         (DVTARGETDEVICE*)CoTaskMemAlloc(ptdSrc->tdSize);
  1256.     if (ptdDest == NULL)
  1257.         return NULL;
  1258.  
  1259.     memcpy(ptdDest, ptdSrc, (size_t)ptdSrc->tdSize);
  1260.     return ptdDest;
  1261. }
  1262.  
  1263. void AFXAPI _AfxOleCopyFormatEtc(LPFORMATETC petcDest, LPFORMATETC petcSrc)
  1264. {
  1265.     ASSERT(petcDest != NULL);
  1266.     ASSERT(petcSrc != NULL);
  1267.  
  1268.     petcDest->cfFormat = petcSrc->cfFormat;
  1269.     petcDest->ptd = _AfxOleCopyTargetDevice(petcSrc->ptd);
  1270.     petcDest->dwAspect = petcSrc->dwAspect;
  1271.     petcDest->lindex = petcSrc->lindex;
  1272.     petcDest->tymed = petcSrc->tymed;
  1273. }
  1274.  
  1275. HDC WINAPI _AfxOleCreateDC(DVTARGETDEVICE* ptd)
  1276. {
  1277.     USES_CONVERSION;
  1278.  
  1279.     // return screen DC for NULL target device
  1280.     if (ptd == NULL)
  1281.         return ::CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
  1282.  
  1283.     LPDEVMODEOLE lpDevMode;
  1284.     LPOLESTR lpszDriverName;
  1285.     LPOLESTR lpszDeviceName;
  1286.     LPOLESTR lpszPortName;
  1287.  
  1288.     if (ptd->tdExtDevmodeOffset == 0)
  1289.         lpDevMode = NULL;
  1290.     else
  1291.         lpDevMode  = (LPDEVMODEOLE) ((LPSTR)ptd + ptd->tdExtDevmodeOffset);
  1292.  
  1293.     lpszDriverName = (LPOLESTR)((BYTE*)ptd + ptd->tdDriverNameOffset);
  1294.     lpszDeviceName = (LPOLESTR)((BYTE*)ptd + ptd->tdDeviceNameOffset);
  1295.     lpszPortName   = (LPOLESTR)((BYTE*)ptd + ptd->tdPortNameOffset);
  1296.  
  1297.     return ::CreateDC(OLE2CT(lpszDriverName), OLE2CT(lpszDeviceName),
  1298.         OLE2CT(lpszPortName), DEVMODEOLE2T(lpDevMode));
  1299. }
  1300.  
  1301. void AFXAPI _AfxDeleteMetafilePict(HGLOBAL hMetaPict)
  1302. {
  1303.     if (hMetaPict != NULL)
  1304.     {
  1305.         STGMEDIUM stgMedium;
  1306.         stgMedium.hGlobal = hMetaPict;
  1307.         stgMedium.tymed = TYMED_MFPICT;
  1308.         stgMedium.pUnkForRelease = NULL;
  1309.         ReleaseStgMedium(&stgMedium);
  1310.     }
  1311. }
  1312.  
  1313. #define HIMETRIC_PER_INCH   2540
  1314. #define MAP_PIX_TO_LOGHIM(x,ppli)   MulDiv(HIMETRIC_PER_INCH, (x), (ppli))
  1315. #define MAP_LOGHIM_TO_PIX(x,ppli)   MulDiv((ppli), (x), HIMETRIC_PER_INCH)
  1316.  
  1317. void AFXAPI _AfxXformSizeInPixelsToHimetric(
  1318.     HDC hDC, LPSIZEL lpSizeInPix, LPSIZEL lpSizeInHiMetric)
  1319. {
  1320.     int cxPPI;
  1321.     int cyPPI;
  1322.  
  1323.     if ((NULL == hDC) || (GetDeviceCaps(hDC, LOGPIXELSX) == 0))
  1324.     {
  1325.         cxPPI = afxData.cxPixelsPerInch;
  1326.         cyPPI = afxData.cyPixelsPerInch;
  1327.     }
  1328.     else
  1329.     {
  1330.         cxPPI = GetDeviceCaps(hDC, LOGPIXELSX);
  1331.         cyPPI = GetDeviceCaps(hDC, LOGPIXELSY);
  1332.     }
  1333.  
  1334.     lpSizeInHiMetric->cx = (long)MAP_PIX_TO_LOGHIM((int)lpSizeInPix->cx, cxPPI);
  1335.     lpSizeInHiMetric->cy = (long)MAP_PIX_TO_LOGHIM((int)lpSizeInPix->cy, cyPPI);
  1336. }
  1337.  
  1338. void AFXAPI _AfxXformSizeInHimetricToPixels(
  1339.     HDC hDC, LPSIZEL lpSizeInHiMetric, LPSIZEL lpSizeInPix)
  1340. {
  1341.     int cxPPI;
  1342.     int cyPPI;
  1343.  
  1344.     if ((NULL == hDC) || (GetDeviceCaps(hDC, LOGPIXELSX) == 0))
  1345.     {
  1346.         cxPPI = afxData.cxPixelsPerInch;
  1347.         cyPPI = afxData.cyPixelsPerInch;
  1348.     }
  1349.     else
  1350.     {
  1351.         cxPPI = GetDeviceCaps(hDC, LOGPIXELSX);
  1352.         cyPPI = GetDeviceCaps(hDC, LOGPIXELSY);
  1353.     }
  1354.  
  1355.     lpSizeInPix->cx = (long)MAP_LOGHIM_TO_PIX((int)lpSizeInHiMetric->cx, cxPPI);
  1356.     lpSizeInPix->cy = (long)MAP_LOGHIM_TO_PIX((int)lpSizeInHiMetric->cy, cyPPI);
  1357. }
  1358.  
  1359. #ifdef AFX_INIT_SEG
  1360. #pragma code_seg(AFX_INIT_SEG)
  1361. #endif
  1362.  
  1363. IMPLEMENT_DYNAMIC(COleException, CException)
  1364.  
  1365. /////////////////////////////////////////////////////////////////////////////
  1366.