home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 39 / IOPROG_39.ISO / SOFT / sdkjava40.exe / data1.cab / fg_Samples / Samples / COM / CustomMarshal / client / CustSample.cpp next >
Encoding:
C/C++ Source or Header  |  2000-05-04  |  28.6 KB  |  1,047 lines

  1. /*++
  2.  
  3.     (C) Copyright 1995 - 1999 Microsoft Corporation.  All rights reserved.
  4.  
  5.  
  6.  
  7.  
  8. --*/
  9.  
  10.  
  11.  
  12.  
  13. #pragma hdrstop
  14.  
  15.  
  16. #define INITGUID 1
  17.  
  18. #include <windows.h>
  19. #include <stdio.h>
  20. #include <olectl.h>          // to get the SELFREF_E_CLASS definition
  21.  
  22.  
  23. #define MYCHAR CHAR
  24. #include "debug\\CustSample.h"  // ICustSample defn (generated from CustSample.odl).
  25.  
  26.  
  27.  
  28. //=======================================================================
  29. // CCustSample
  30. //
  31. //   This class implements our COM object which exposes only one interface
  32. //   (ICustSample).
  33. //
  34. //   Strictly speaking, it should also expose IMarshal by aggregating the
  35. //   Ole free-threaded marshaler, since this dll marks itself "Both."
  36. //   For such a simple sample, however, this will not matter.
  37. //=======================================================================
  38. class CCustSample : public ICustSample {
  39.     private:
  40.         ULONG       m_ref;          // Reference count.
  41.  
  42.     public:
  43.         CCustSample() {
  44.             m_ref = 0;
  45.         }
  46.  
  47.         //-------------------------------------------------------
  48.         // IUnknown methods.
  49.         //-------------------------------------------------------
  50.         STDMETHOD(QueryInterface) (REFIID riid, LPVOID *ppv) {
  51.             __try {
  52.                 *ppv = NULL;
  53.             } __except (EXCEPTION_EXECUTE_HANDLER) {
  54.                 return E_POINTER;
  55.             }
  56.  
  57.             if (riid == IID_IUnknown || riid == IID_ICustSample) {
  58.                 AddRef();
  59.                 *ppv = (ICustSample*)this;
  60.                 return S_OK;
  61.             }
  62.             return E_NOINTERFACE;
  63.         }
  64.  
  65.         STDMETHOD_(ULONG, AddRef) () {
  66.             InterlockedIncrement( (LONG*)&m_ref );
  67.             return 1;
  68.         }
  69.  
  70.         STDMETHOD_(ULONG, Release) () {
  71.             LONG ulc;
  72.  
  73.             ulc = InterlockedDecrement( (LONG*)&m_ref );
  74.             if (ulc < 0) {
  75.                 OutputDebugString("Too many releases on CCustSample object!\n");
  76.                 DebugBreak();
  77.             }
  78.             if (0 == ulc) {
  79.                 OutputDebugString("CCustSample: Destroy\n");
  80.                 delete this;
  81.                 return 0;
  82.             }
  83.             return 1;
  84.         }
  85.  
  86.  
  87.         //-------------------------------------------------------
  88.         // ICustSample methods.
  89.         //-------------------------------------------------------
  90.         STDMETHOD(PassFixedPtIn)(FIXED fp)
  91.         {
  92.             printf("C PassFixedPtIn called: (%ld, %lu)\n",
  93.                    (LONG)(fp.value),
  94.                    (ULONG)(fp.fract));
  95.             return S_OK;
  96.         }
  97.  
  98.         STDMETHOD(PassPFixedPtOutRetVal)(FIXED *pfp)
  99.         {
  100.             printf("C PassPFixedPtOutRetVal called. Returning 7.25\n");
  101.             pfp->value = 7;
  102.             pfp->fract = 16384;
  103.             return S_OK;
  104.         }
  105.  
  106.         STDMETHOD(PassPFixedPtIn)(FIXED *pfp)
  107.         {
  108.             printf("C PassPFixedPtIn called: (%ld, %lu)\n",
  109.                    (LONG)(pfp->value),
  110.                    (ULONG)(pfp->fract));
  111.             return S_OK;
  112.         }
  113.  
  114.         STDMETHOD(PassPFixedPtOut)(FIXED *pfp)
  115.         {
  116.             printf("C PassPFixedPtOut called. Returning 3.25\n");
  117.             pfp->value = 3;
  118.             pfp->fract = 16384;
  119.             return S_OK;
  120.         }
  121.  
  122.         STDMETHOD(PassPFixedPtInOut)(FIXED *pfp)
  123.         {
  124.             printf("C PassPFixedPtInOut called. Incrementing value by 2.\n");
  125.             pfp->value += 2;
  126.             return S_OK;
  127.         }
  128.  
  129.         STDMETHOD(PassFixedPtsFromComToJava)(ICustSample *obj)
  130.         {
  131.  
  132.             // This method demonstrates invoking Java methods from COM.
  133.             // It accepts an ICustSample interface pointer (whose implementation
  134.             // will be in Java, though this method is naturally oblivious
  135.             // to that), and invokes every single method on it.
  136.  
  137.             HRESULT hr;
  138.  
  139.             {
  140.                 FIXED f = {32768, 4};
  141.                 hr = obj->PassFixedPtIn(f);
  142.                 if (S_OK != hr) {
  143.                     return hr;
  144.                 }
  145.             }
  146.  
  147.             {
  148.                 FIXED f = {0, 0};
  149.                 hr = obj->PassPFixedPtOutRetVal(&f);
  150.                 if (S_OK != hr) {
  151.                     return hr;
  152.                 }
  153.                 printf("(%ld, %lu)\n", (LONG)(f.value), (ULONG)(f.fract));
  154.             }
  155.             {
  156.                 FIXED f = {32768, 8};
  157.                 hr = obj->PassPFixedPtIn(&f);
  158.                 if (S_OK != hr) {
  159.                     return hr;
  160.                 }
  161.             }
  162.             {
  163.                 FIXED f = {0, 0};
  164.                 hr = obj->PassPFixedPtOut(&f);
  165.                 if (S_OK != hr) {
  166.                     return hr;
  167.                 }
  168.                 printf("(%ld, %lu)\n", (LONG)(f.value), (ULONG)(f.fract));
  169.             }
  170.  
  171.             {
  172.                 FIXED f = {16384, 8};
  173.                 hr = obj->PassPFixedPtInOut(&f);
  174.                 if (S_OK != hr) {
  175.                     return hr;
  176.                 }
  177.                 printf("(%ld, %lu)\n", (LONG)(f.value), (ULONG)(f.fract));
  178.             }
  179.  
  180.  
  181.             return S_OK;
  182.  
  183.  
  184.         }
  185.  
  186.  
  187.  
  188.  
  189.         STDMETHOD(PassMyVariantIn)(MYVARIANT v)
  190.         {
  191.             printf("C PassMyVariantIn called: ");
  192.             PrintBSTR(v.bstrVal);
  193.             printf("\n");
  194.             return S_OK;
  195.         }
  196.  
  197.         STDMETHOD(PassPMyVariantOutRetVal)(MYVARIANT* pv)
  198.         {
  199.             printf("C PassPMyVariantOutRetVal called.\n");
  200.             pv->vt = VT_BSTR;
  201.             pv->bstrVal = NewBSTR(L"If you can read this, PassPMyVariantOutRetVal works.");
  202.             return S_OK;
  203.         }
  204.  
  205.         STDMETHOD(PassPMyVariantIn)(MYVARIANT *pv)
  206.         {
  207.             printf("C PassPMyVariantIn called: ");
  208.             PrintBSTR(pv->bstrVal);
  209.             printf("\n");
  210.             return S_OK;
  211.         }
  212.  
  213.         STDMETHOD(PassPMyVariantOut)(MYVARIANT* pv)
  214.         {
  215.             printf("C PassPMyVariantOut called.\n");
  216.             pv->vt = VT_BSTR;
  217.             pv->bstrVal = NewBSTR(L"If you can read this, PassPMyVariantOut works.");
  218.             return S_OK;
  219.         }
  220.  
  221.         STDMETHOD(PassPMyVariantInOut)(MYVARIANT* pv)
  222.         {
  223.             printf("C PassPMyVariantInOut called: ");
  224.             PrintBSTR(pv->bstrVal);
  225.             printf("\n");
  226.  
  227.             FreeBSTR(pv->bstrVal);
  228.         
  229.             pv->vt = VT_BSTR;
  230.             pv->bstrVal = NewBSTR(L"If you can read this, the 'out' part of PassPMyVariantInOut works.");
  231.             return S_OK;
  232.         }
  233.  
  234.         STDMETHOD(PassMyVariantFromComToJava)(ICustSample *obj)
  235.         {
  236.  
  237.             // This method demonstrates invoking Java methods from COM.
  238.             // It accepts an ICustSample interface pointer (whose implementation
  239.             // will be in Java, though this method is naturally oblivious
  240.             // to that), and invokes every single method on it.
  241.  
  242.             HRESULT hr;
  243.             {
  244.                 MYVARIANT mv;
  245.                 mv.vt = VT_BSTR;
  246.                 mv.bstrVal = NewBSTR(L"If you can read this, PassMyVariantIn worked.");
  247.                 hr = obj->PassMyVariantIn(mv);
  248.                 if (S_OK != hr) {
  249.                     return hr;
  250.                 }
  251.                 FreeBSTR(mv.bstrVal);
  252.             }
  253.  
  254.             {
  255.                 MYVARIANT mv;
  256.                 FillMemory(&mv, sizeof(mv), 0xcc);
  257.  
  258.                 hr = obj->PassPMyVariantOutRetVal(&mv);
  259.                 if (S_OK != hr) {
  260.                     return hr;
  261.                 }
  262.                 PrintBSTR(mv.bstrVal);
  263.                 printf("\n");
  264.                 FreeBSTR(mv.bstrVal);
  265.             }
  266.  
  267.             {
  268.                 MYVARIANT mv;
  269.                 mv.vt = VT_BSTR;
  270.                 mv.bstrVal = NewBSTR(L"If you can read this, PPassMyVariantIn worked.");
  271.                 hr = obj->PassPMyVariantIn(&mv);
  272.                 if (S_OK != hr) {
  273.                     return hr;
  274.                 }
  275.                 FreeBSTR(mv.bstrVal);
  276.             }
  277.  
  278.             {
  279.                 MYVARIANT mv;
  280.                 FillMemory(&mv, sizeof(mv), 0xcc);
  281.  
  282.                 hr = obj->PassPMyVariantOut(&mv);
  283.                 if (S_OK != hr) {
  284.                     return hr;
  285.                 }
  286.                 PrintBSTR(mv.bstrVal);
  287.                 printf("\n");
  288.                 FreeBSTR(mv.bstrVal);
  289.             }
  290.             {
  291.                 MYVARIANT mv;
  292.                 mv.vt = VT_BSTR;
  293.                 mv.bstrVal = NewBSTR(L"If you can read this, the 'in' part of PPassMyVariantInOut worked.");
  294.  
  295.                 hr = obj->PassPMyVariantInOut(&mv);
  296.                 if (S_OK != hr) {
  297.                     return hr;
  298.                 }
  299.                 PrintBSTR(mv.bstrVal);
  300.                 printf("\n");
  301.                 FreeBSTR(mv.bstrVal);
  302.             }
  303.  
  304.             return S_OK;
  305.         }
  306.  
  307.  
  308.         STDMETHOD(PassPPointOut)(POINT* ppt)
  309.         {
  310.             printf("C PassPPointOut called. Returning [5,6]\n");
  311.             ppt->x = 5;
  312.             ppt->y = 6;
  313.             return S_OK;
  314.         }
  315.  
  316.         STDMETHOD(PassPPointInOut)(POINT* ppt)
  317.         {
  318.             printf("C PassPPointInOut called. Received [%ld,%ld]. Translating x & y by 3.\n", ppt->x, ppt->y);
  319.             ppt->x += 3;
  320.             ppt->y += 3;
  321.             return S_OK;
  322.         }
  323.  
  324.         STDMETHOD(PassPointFromComToJava)(ICustSample *obj)
  325.         {
  326.  
  327.             // This method demonstrates invoking Java methods from COM.
  328.             // It accepts an ICustSample interface pointer (whose implementation
  329.             // will be in Java, though this method is naturally oblivious
  330.             // to that), and invokes every single method on it.
  331.  
  332.             HRESULT hr;
  333.             {
  334.                 POINT p = {-1,-1};
  335.                 hr = obj->PassPPointOut(&p);
  336.                 if (hr != S_OK) {
  337.                     return hr;
  338.                 }
  339.                 printf("[%ld,%ld]\n", p.x, p.y);
  340.             }
  341.  
  342.             {
  343.                 POINT p = {10,11};
  344.                 hr = obj->PassPPointInOut(&p);
  345.                 if (hr != S_OK) {
  346.                     return hr;
  347.                 }
  348.                 printf("[%ld,%ld]\n", p.x, p.y);
  349.             }
  350.             return S_OK;
  351.         }
  352.  
  353.         STDMETHOD(PassRectIn)(RECT r)
  354.         {
  355.             printf("C PassRectIn called: ");
  356.             PrintRect(r);
  357.             printf("\n");
  358.             return S_OK;
  359.         }
  360.  
  361.         STDMETHOD(PassPRectOutRetVal)(RECT *pr)
  362.         {
  363.             RECT r = {4,5,10,11};
  364.             printf("C PassPRectOutRetVal called. Returning ");
  365.             PrintRect(r);
  366.             printf("\n");
  367.             *pr = r;
  368.             return S_OK;
  369.         }
  370.  
  371.         STDMETHOD(PassPRectIn)(RECT *pr)
  372.         {
  373.             printf("C PassPRectIn called: ");
  374.             PrintRect(*pr);
  375.             printf("\n");
  376.             return S_OK;
  377.         }
  378.  
  379.         STDMETHOD(PassPRectOut)(RECT *pr)
  380.         {
  381.             RECT r = {7,8,20,31};
  382.             printf("C PassPRectOutRetVal called. Returning ");
  383.             PrintRect(r);
  384.             printf("\n");
  385.             *pr = r;
  386.             return S_OK;
  387.         }
  388.  
  389.         STDMETHOD(PassPRectInOut)(RECT *pr)
  390.         {
  391.             printf("C PassPRectInOut called. Moving rectangle by (2,2)\n");
  392.             pr->left   += 2;
  393.             pr->top    += 2;
  394.             pr->right  += 2;
  395.             pr->bottom += 2;
  396.  
  397.             return S_OK;
  398.         }
  399.  
  400.  
  401.         STDMETHOD(PassPPRectOutRetVal)(RECT **ppr)
  402.         {
  403.  
  404.             *ppr = NewRect(6,7,8,9);
  405.             printf("C PassPPRectOutRetVal called. Returning ");
  406.             PrintRect(**ppr);
  407.             printf("\n");
  408.             return S_OK;
  409.         }
  410.  
  411.         STDMETHOD(PassPPRectIn)(RECT **ppr)
  412.         {
  413.             printf("C PassPPRectIn called: ");
  414.             PrintRect(**ppr);
  415.             printf("\n");
  416.             return S_OK;
  417.         }
  418.  
  419.         STDMETHOD(PassPPRectOut)(RECT **ppr)
  420.         {
  421.  
  422.             *ppr = NewRect(13,14,15,16);
  423.             printf("C PassPPRectOutcalled. Returning ");
  424.             PrintRect(**ppr);
  425.             printf("\n");
  426.             return S_OK;
  427.         }
  428.  
  429.         STDMETHOD(PassPPRectInOut)(RECT **ppr)
  430.         {
  431.  
  432.             printf("C PassPPRectInOut called: ");
  433.             PrintRect(**ppr);
  434.             printf("\n");
  435.  
  436.             FreeRect(*ppr);
  437.  
  438.             *ppr = NewRect(1,2,3,4);
  439.             printf("C PassPPRectInOut called. Returning ");
  440.             PrintRect(**ppr);
  441.             printf("\n");
  442.             return S_OK;
  443.         }
  444.  
  445.         STDMETHOD(PassRectFromComToJava)(ICustSample *obj)
  446.         {
  447.  
  448.             // This method demonstrates invoking Java methods from COM.
  449.             // It accepts an ICustSample interface pointer (whose implementation
  450.             // will be in Java, though this method is naturally oblivious
  451.             // to that), and invokes every single method on it.
  452.  
  453.             HRESULT hr;
  454.             {
  455.                 RECT r = {4,5,6,7};
  456.                 PrintRect(r);printf("\n");
  457.                 hr = obj->PassRectIn(r);
  458.                 if (S_OK != hr) {
  459.                     return hr;
  460.                 }
  461.             }
  462.             {
  463.                 RECT r = {-1,-1,-1,-1};
  464.                 hr = obj->PassPRectOutRetVal(&r);
  465.                 if (S_OK != hr) {
  466.                     return hr;
  467.                 }
  468.                 PrintRect(r);printf("\n");
  469.             }
  470.             {
  471.                 RECT r = {14,15,16,17};
  472.                 PrintRect(r);printf("\n");
  473.                 hr = obj->PassPRectIn(&r);
  474.                 if (S_OK != hr) {
  475.                     return hr;
  476.                 }
  477.             }
  478.             {
  479.                 RECT r = {-1,-1,-1,-1};
  480.                 hr = obj->PassPRectOut(&r);
  481.                 if (S_OK != hr) {
  482.                     return hr;
  483.                 }
  484.                 PrintRect(r);printf("\n");
  485.             }
  486.             {
  487.                 RECT r = {24,25,26,27};
  488.                 hr = obj->PassPRectInOut(&r);
  489.                 if (S_OK != hr) {
  490.                     return hr;
  491.                 }
  492.                 PrintRect(r);printf("\n");
  493.             }
  494.             {
  495.                 RECT *pr = NULL;
  496.                 hr = obj->PassPPRectOutRetVal(&pr);
  497.                 if (S_OK != hr) {
  498.                     return hr;
  499.                 }
  500.                 PrintRect(*pr);printf("\n");
  501.                 FreeRect(pr);
  502.             }
  503.             {
  504.                 RECT r = {44,45,46,47};
  505.                 PRECT pr = &r;
  506.                 hr = obj->PassPPRectIn(&pr);
  507.                 if (S_OK != hr) {
  508.                     return hr;
  509.                 }
  510.             }
  511.  
  512.             {
  513.                 RECT *pr = NULL;
  514.                 hr = obj->PassPPRectOut(&pr);
  515.                 if (S_OK != hr) {
  516.                     return hr;
  517.                 }
  518.                 PrintRect(*pr);printf("\n");
  519.                 FreeRect(pr);
  520.             }
  521.             {
  522.                 RECT *pr = NewRect(55,56,57,58);
  523.                 hr = obj->PassPPRectInOut(&pr);
  524.                 if (S_OK != hr) {
  525.                     return hr;
  526.                 }
  527.                 PrintRect(*pr);printf("\n");
  528.                 FreeRect(pr);
  529.             }
  530.             return S_OK;
  531.         }
  532.  
  533.  
  534.         STDMETHOD(PassPStrIn)(LPSTR pstr)
  535.         {
  536.             printf("C PassPStrIn called: '%s'\n", pstr);
  537.             return S_OK;
  538.         }
  539.  
  540.  
  541.  
  542.         STDMETHOD(PassPPStrOutRetVal)(LPSTR *ppstr)
  543.         {
  544.             *ppstr = NewStr("If you can read this, C PassPPStrOutRetVal works.");
  545.             return S_OK;
  546.         }
  547.  
  548.         STDMETHOD(PassPPStrIn)(LPSTR *ppstr)
  549.         {
  550.             printf("C PassPPStrIn called: '%s'\n", *ppstr);
  551.             return S_OK;
  552.         }
  553.  
  554.         STDMETHOD(PassPPStrOut)(LPSTR *ppstr)
  555.         {
  556.             *ppstr = NewStr("If you can read this, C PassPPStrOut works.");
  557.             return S_OK;
  558.         }
  559.  
  560.         STDMETHOD(PassPPStrInOut)(LPSTR *ppstr)
  561.         {
  562.             printf("C PassPPStrInOut called: '%s'\n", *ppstr);
  563.             FreeStr(*ppstr);
  564.             *ppstr = NewStr("If you can read this, 'out' part of C PassPPStrInOut works.");
  565.             return S_OK;
  566.         }
  567.  
  568.  
  569.         STDMETHOD(PassAnsiFromComToJava)(ICustSample *obj)
  570.         {
  571.  
  572.             // This method demonstrates invoking Java methods from COM.
  573.             // It accepts an ICustSample interface pointer (whose implementation
  574.             // will be in Java, though this method is naturally oblivious
  575.             // to that), and invokes every single method on it.
  576.  
  577.             HRESULT hr;
  578.             {
  579.                 hr = obj->PassPStrIn("If you can read this, Java PassPStrIn works.");
  580.                 if (S_OK != hr) {
  581.                     return hr;
  582.                 }
  583.             }
  584.             {
  585.                 LPSTR pstr = (LPSTR)0xcccccccc;
  586.                 hr = obj->PassPPStrOutRetVal(&pstr);
  587.                 if (S_OK != hr) {
  588.                     return hr;
  589.                 }
  590.                 printf("%s\n", pstr);
  591.                 FreeStr(pstr);
  592.             }
  593.             {
  594.                 LPSTR pstr = "If you can read this, Java PassPPStrIn works.";
  595.                 hr = obj->PassPPStrIn(&pstr);
  596.                 if (S_OK != hr) {
  597.                     return hr;
  598.                 }
  599.             }
  600.             {
  601.                 LPSTR pstr = (LPSTR)0xcccccccc;
  602.                 hr = obj->PassPPStrOut(&pstr);
  603.                 if (S_OK != hr) {
  604.                     return hr;
  605.                 }
  606.                 printf("%s\n", pstr);
  607.                 FreeStr(pstr);
  608.             }
  609.             {
  610.                 LPSTR pstr = NewStr("If you can read this, 'in' part of Java PassPPStrInOut works.");
  611.                 hr = obj->PassPPStrInOut(&pstr);
  612.                 if (S_OK != hr) {
  613.                     return hr;
  614.                 }
  615.                 printf("%s\n", pstr);
  616.                 FreeStr(pstr);
  617.             }
  618.  
  619.             return S_OK;
  620.         }
  621.  
  622.     private:
  623.  
  624.         //------------------------------------------------------------
  625.         // Some simple utilities.
  626.         //------------------------------------------------------------
  627.         BSTR NewBSTR(LPCWSTR sz)
  628.         {
  629.             BSTR bstr = SysAllocString(sz);
  630.             if (!bstr) {
  631.                 printf("Out of BSTR heap space.\n");
  632.                 exit(1);
  633.             }
  634.  
  635.             CHAR msg[100];
  636.             wsprintf(msg, "Server allocated BSTR at %lxh\n", bstr);
  637.             OutputDebugString(msg);
  638.             return bstr;
  639.         }
  640.  
  641.         VOID FreeBSTR(BSTR bstr)
  642.         {
  643.             CHAR msg[100];
  644.             wsprintf(msg, "Server freeing BSTR at %lxh\n", bstr);
  645.             OutputDebugString(msg);
  646.  
  647.             SysFreeString(bstr);
  648.         }
  649.  
  650.         VOID PrintBSTR(BSTR bstr)
  651.         {
  652.             DWORD len = SysStringLen(bstr);
  653.             DWORD i;
  654.             putchar('"');
  655.             for (i = 0; i < len; i++) {
  656.                 putchar((CHAR)(bstr[i]));
  657.             }
  658.             putchar('"');
  659.         }
  660.  
  661.  
  662.         VOID PrintRect(RECT r)
  663.         {
  664.             printf("[x=%ld,y=%ld,width=%ld,height=%ld]",
  665.                    r.left,
  666.                    r.top,
  667.                    r.right - r.left,
  668.                    r.bottom - r.top);
  669.         }
  670.  
  671.         RECT *NewRect(long x, long y, long width, long height)
  672.         {
  673.             RECT* pr = (RECT*)CoTaskMemAlloc(sizeof(RECT) + 1);
  674.             if (!pr) {
  675.                 printf("Out of task heap space.\n");
  676.                 exit(1);
  677.             }
  678.  
  679.             pr->left    = x;
  680.             pr->top     = y;
  681.             pr->right   = x + width;
  682.             pr->bottom  = y + height;
  683.  
  684.             CHAR msg[100];
  685.             wsprintf(msg, "Server allocated RECT at %lxh\n", pr);
  686.             OutputDebugString(msg);
  687.  
  688.  
  689.             return pr;
  690.         }
  691.  
  692.         VOID FreeRect(RECT *pr)
  693.         {
  694.             CHAR msg[100];
  695.             wsprintf(msg, "Server freeing RECT at %lxh\n", pr);
  696.             OutputDebugString(msg);
  697.  
  698.             CoTaskMemFree(pr);
  699.         }
  700.  
  701.         LPSTR NewStr(LPCSTR sz)
  702.         {
  703.             LPSTR pstr = (LPSTR)CoTaskMemAlloc(lstrlen(sz) + 1);
  704.             if (!pstr) {
  705.                 printf("Out of heap space.\n");
  706.                 exit(1);
  707.             }
  708.  
  709.             lstrcpy(pstr, sz);
  710.  
  711.             CHAR msg[100];
  712.             wsprintf(msg, "Server allocated Str at %lxh\n", pstr);
  713.             OutputDebugString(msg);
  714.             return pstr;
  715.         }
  716.  
  717.         VOID FreeStr(LPSTR pstr)
  718.         {
  719.             CHAR msg[100];
  720.             wsprintf(msg, "Server freeing Str at %lxh\n", pstr);
  721.             OutputDebugString(msg);
  722.  
  723.             CoTaskMemFree(pstr);
  724.         }
  725.  
  726. };
  727.  
  728.  
  729. //=======================================================================
  730. // J2CClassFactory
  731. //
  732. //   This class implements the classfactory for our COM server. Since our
  733. //   classfactory has no intrinsic state, we use a static class factory
  734. //   to simplify our implementation.
  735. //   
  736. //=======================================================================
  737. class J2CClassFactory : public IClassFactory
  738. {
  739.     public:
  740.  
  741.         //-----------------------------------------------------------
  742.         // IUnknown methods.
  743.         //-----------------------------------------------------------
  744.         STDMETHOD(QueryInterface) (REFIID riid, LPVOID *ppv)
  745.         {
  746.             __try {
  747.                 *ppv = NULL;
  748.             } __except (EXCEPTION_EXECUTE_HANDLER) {
  749.                 return E_POINTER;
  750.             }
  751.  
  752.             if (riid == IID_IUnknown || riid == IID_IClassFactory) {
  753.                 AddRef();
  754.                 *ppv = (IClassFactory*)this;
  755.                 return S_OK;
  756.             }
  757.             return E_NOINTERFACE;
  758.         }
  759.  
  760.         STDMETHOD_(ULONG, AddRef) () {
  761.             return 1;
  762.         }
  763.  
  764.         STDMETHOD_(ULONG, Release) () {
  765.             return 1;
  766.         }
  767.  
  768.         //-----------------------------------------------------------
  769.         // IClassFactory methods.
  770.         //-----------------------------------------------------------
  771.         STDMETHOD(CreateInstance)(IUnknown *punkOuter, REFIID riid, LPVOID *ppv)
  772.         {
  773.             *ppv = NULL;
  774.  
  775.             if (punkOuter != NULL) {
  776.                 return CLASS_E_NOAGGREGATION;
  777.             }
  778.  
  779.             CCustSample *pJ2CThing;
  780.             HRESULT hr;
  781.  
  782.             pJ2CThing = new CCustSample();
  783.             if (!pJ2CThing) {
  784.                 return E_OUTOFMEMORY;
  785.             }
  786.         
  787.             pJ2CThing->AddRef();
  788.             hr = pJ2CThing->QueryInterface(riid, ppv);
  789.             pJ2CThing->Release();
  790.             return hr;
  791.         }
  792.  
  793.         STDMETHOD(LockServer)(BOOL fLock) {
  794.             return S_OK;
  795.             }
  796.  
  797. };
  798.  
  799.  
  800. //===================================================================
  801. // Create our first (and only) classfactory.
  802. //===================================================================
  803. J2CClassFactory g_CF;
  804.  
  805.  
  806. // Rememeber our dll's module handle.
  807. HINSTANCE ghInstance;
  808.  
  809.  
  810.  
  811.  
  812. //===================================================================
  813. // Standard DLL entry point (called by Win32 loader.)
  814. //===================================================================
  815. BOOL WINAPI DllMain(HINSTANCE hmod, DWORD dwReason,
  816.                                 PVOID pvReserved)
  817. {
  818.    ghInstance = hmod;
  819.  
  820.    if (dwReason == DLL_PROCESS_ATTACH) {
  821.         OutputDebugString("CustSample.dll has successfully loaded.\n");
  822.    }
  823.  
  824.    return TRUE;
  825. }
  826.  
  827.  
  828.  
  829.  
  830.  
  831.  
  832. //===================================================================
  833. // Standard Ole export ("creates" a classfactory.)
  834. //===================================================================
  835. STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
  836. {
  837.  
  838.     HRESULT hr;
  839.  
  840.     __try {
  841.         *ppv = NULL;
  842.     } __except (EXCEPTION_EXECUTE_HANDLER) {
  843.         return E_POINTER;
  844.     }
  845.  
  846.     if (rclsid != CLSID_CCustSample) {
  847.         return CLASS_E_CLASSNOTAVAILABLE;
  848.     }
  849.  
  850.     return g_CF.QueryInterface(riid, ppv);
  851.  
  852.  
  853. }
  854.  
  855.  
  856.  
  857.  
  858. //===================================================================
  859. // Simple GUID unparsing utility (for self-registering code).
  860. //===================================================================
  861.  
  862.  
  863. #define GUIDSTR_MAX (1+ 8 + 1 + 4 + 1 + 4 + 1 + 4 + 1 + 12 + 1 + 1)
  864.  
  865. static const CHAR szDigits[] = "0123456789ABCDEF";
  866. static const BYTE GuidMap[] = { 3, 2, 1, 0, '-', 5, 4, '-', 7, 6, '-',
  867.                                 8, 9, '-', 10, 11, 12, 13, 14, 15 };
  868.  
  869.  
  870. //--------------------------------------------------------------------------
  871. //
  872. //  Function:   GUID2StringA
  873. //
  874. //  Synopsis:   Convert GUID to string form
  875. //
  876. //  Arguments:  [rguid] - the guid to convert
  877. //              [lpszy] - buffer to hold the results
  878. //
  879. //  Returns:    nothing
  880. //
  881. //  This code is massively plagiarized from the Ole sources.
  882. //--------------------------------------------------------------------------
  883.  
  884. VOID
  885. GUID2StringA(REFGUID rguid, LPSTR lpsz)
  886. {
  887.     int i;
  888.     LPSTR p = lpsz;
  889.  
  890.     const BYTE * pBytes = (const BYTE *) &rguid;
  891.  
  892.     *p++ = '{';
  893.  
  894.     for (i = 0; i < sizeof(GuidMap); i++)
  895.     {
  896.         if (GuidMap[i] == '-')
  897.         {
  898.             *p++ = '-';
  899.         }
  900.         else
  901.         {
  902.             *p++ = szDigits[ (pBytes[GuidMap[i]] & 0xF0) >> 4 ];
  903.             *p++ = szDigits[ (pBytes[GuidMap[i]] & 0x0F) ];
  904.         }
  905.     }
  906.     *p++ = '}';
  907.     *p   = '\0';
  908. }
  909.  
  910.  
  911.  
  912. const char achTM[] = "Both";
  913. const char achDESC[] = "Sample Custom Marshaling Server.";
  914. const char achPROGID[] = "CCustSample";
  915.  
  916.  
  917. //===================================================================
  918. // Standard Ole export (for self-registration a la regsvr32.)
  919. //===================================================================
  920. __declspec(dllexport)
  921. STDAPI
  922. DllRegisterServer(VOID)
  923. {
  924.    HKEY    hKey  = NULL;
  925.    HKEY    hKey2 = NULL;
  926.    HKEY    hKey3 = NULL;
  927.    DWORD   result;
  928.    HRESULT hr = SELFREG_E_CLASS;
  929.    CHAR    achCLSID[GUIDSTR_MAX];
  930.    TCHAR   achModulePathName[MAX_PATH];
  931.  
  932.    // If we fail in the middle, the state of the registry entries
  933.    // is indeterminate (as per Ole specs.)
  934.  
  935.  
  936.    // Create HKEY_CLASSES_ROOT\progid\CLSID
  937.    result = RegCreateKey(HKEY_CLASSES_ROOT, achPROGID, &hKey);
  938.    if (result != ERROR_SUCCESS) {
  939.       goto lExit;
  940.    }
  941.    result = RegSetValue(hKey, NULL, REG_SZ, achDESC, lstrlen(achDESC));
  942.    if (result != ERROR_SUCCESS) {
  943.       goto lExit;
  944.    }
  945.    result = RegCreateKey(hKey, TEXT("CLSID"), &hKey2);
  946.    if (result != ERROR_SUCCESS) {
  947.       goto lExit;
  948.    }
  949.    GUID2StringA(CLSID_CCustSample, achCLSID);
  950.    result = RegSetValue(hKey2, NULL, REG_SZ, achCLSID, GUIDSTR_MAX-1);
  951.    if (result != ERROR_SUCCESS) {
  952.       goto lExit;
  953.    }
  954.  
  955.    RegCloseKey(hKey);
  956.    RegCloseKey(hKey2);
  957.    hKey = NULL;
  958.    hKey2 = NULL;
  959.  
  960.  
  961.    // Create HKEY_CLASSES_ROOT\CLSID\...
  962.    result = RegCreateKey(HKEY_CLASSES_ROOT, TEXT("CLSID"), &hKey);
  963.    if (result != ERROR_SUCCESS) {
  964.       goto lExit;
  965.    }
  966.  
  967.    result = RegCreateKey(hKey, achCLSID, &hKey2);
  968.    if (result != ERROR_SUCCESS) {
  969.       goto lExit;
  970.    }
  971.  
  972.    result = RegSetValue(hKey2, NULL, REG_SZ, achDESC, lstrlen(achDESC));
  973.    if (result != ERROR_SUCCESS) {
  974.       goto lExit;
  975.    }
  976.  
  977.    result = RegCreateKey(hKey2, "InprocServer32", &hKey3);
  978.    if (result != ERROR_SUCCESS) {
  979.       goto lExit;
  980.    }
  981.  
  982.    result = GetModuleFileName(ghInstance, achModulePathName, sizeof(achModulePathName)/sizeof(TCHAR));
  983.    if (result == 0) {  //No way to detect truncation from GetModuleFileName. 
  984.       goto lExit;
  985.    }
  986.  
  987.    result = RegSetValue(hKey3, NULL, REG_SZ, achModulePathName, lstrlen(achModulePathName));
  988.    if (result != ERROR_SUCCESS) {
  989.       goto lExit;
  990.    }
  991.  
  992.    result = RegSetValueEx(hKey3, "ThreadingModel", 0, REG_SZ, (BYTE*)achTM, sizeof(achTM));
  993.    if (result != ERROR_SUCCESS) {
  994.       goto lExit;
  995.    }
  996.  
  997.    RegCloseKey(hKey3);
  998.    hKey3 = NULL;
  999.  
  1000.  
  1001.    result = RegCreateKey(hKey2, "ProgID", &hKey3);
  1002.    if (result != ERROR_SUCCESS) {
  1003.       goto lExit;
  1004.    }
  1005.    result = RegSetValue(hKey3, NULL, REG_SZ, achPROGID, lstrlen(achPROGID));
  1006.    if (result != ERROR_SUCCESS) {
  1007.       goto lExit;
  1008.    }
  1009.    RegCloseKey(hKey3);
  1010.    hKey3 = NULL;
  1011.  
  1012.  
  1013.  
  1014.    hr = S_OK;
  1015.  
  1016.  lExit:
  1017.    if (hKey) {
  1018.       RegCloseKey(hKey);
  1019.    }
  1020.    if (hKey2) {
  1021.       RegCloseKey(hKey2);
  1022.    }
  1023.    if (hKey3) {
  1024.       RegCloseKey(hKey3);
  1025.    }
  1026.    return hr;
  1027.  
  1028. }
  1029.  
  1030.  
  1031.  
  1032. //===================================================================
  1033. // Standard Ole export (for self-unregistration a la regsvr32.)
  1034. //===================================================================
  1035. __declspec(dllexport)
  1036. STDAPI
  1037. DllUnregisterServer(VOID)
  1038. {
  1039.     return S_OK;
  1040. }
  1041.  
  1042.  
  1043.  
  1044.  
  1045.  
  1046.  
  1047.