home *** CD-ROM | disk | FTP | other *** search
/ Power GUI Programming with VisualAge C++ / powergui.iso / trialva / ibmcppw / sdk / mapi / win16 / dev / common / blddt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-07-11  |  27.2 KB  |  827 lines

  1. /*
  2.  *  BLDDT.C
  3.  *
  4.  *  Support for building a display table from resources and data
  5.  *  in memory.
  6.  *
  7.  *  Copyright 1993-1995 Microsoft Corporation. All Rights Reserved.
  8.  */
  9.  
  10. #pragma warning(disable:4001)   /* single line comments */
  11. #pragma warning(disable:4054)   /* cast function pointer to data pointer */
  12. #pragma warning(disable:4100)   /* unreferenced formal parameter */
  13. #pragma warning(disable:4127)   /* conditional expression is constant */
  14. #pragma warning(disable:4201)   /* nameless struct/union */
  15. #pragma warning(disable:4204)   /* non-constant aggregate initializer */
  16. #pragma warning(disable:4209)   /* benign typedef redefinition */
  17. #pragma warning(disable:4214)   /* bit field types other than int */
  18. #pragma warning(disable:4505)   /* unreferenced local function removed */
  19. #pragma warning(disable:4514)   /* unreferenced inline function removed */
  20. #pragma warning(disable:4702)   /* unreachable code */
  21. #pragma warning(disable:4704)   /* inline assembler turns off global optimizer */
  22. #pragma warning(disable:4705)   /* statement has no effect */
  23. #pragma warning(disable:4706)   /* assignment within conditional expression */
  24. #pragma warning(disable:4710)   /* function not expanded */
  25. #pragma warning(disable:4115)   /* named type def in parens */
  26.  
  27. #define _INC_OLE
  28. #include <windows.h>
  29. #pragma warning(disable:4001)   /* single line comments */
  30. #include <windowsx.h>
  31. #include <mapiwin.h>
  32. #include <mapidbg.h>
  33. #include <ole2.h>
  34.  
  35. #include <mapidefs.h>
  36. #include <mapicode.h>
  37. #include <mapitags.h>
  38. #include <mapix.h>
  39. #include <mapispi.h>
  40. #include <mapiguid.h>
  41. #include <stddef.h>
  42. #include <mapiperf.h>
  43. #include <mapiutil.h>
  44.  
  45. #include <_runt.h>
  46. #include <mapixrc.h>
  47.  
  48. #ifdef _MAC
  49. #define LoadResource        AfxLoadResource
  50. #endif
  51.  
  52. #include <_memcpy.h>
  53.  
  54. #pragma SEGMENT(DispTbl)
  55.  
  56. #ifndef WIN32
  57. /*  Windows structures documented for Win16 but not defined in SDK */
  58. /*  Snitched from \capone\inc\ourtypes.h 12/29/93 */
  59.  
  60. #pragma pack(1)
  61.  
  62. typedef struct {
  63.     DWORD   style;
  64.     BYTE    cdit;
  65.     WORD    x;
  66.     WORD    y;
  67.     WORD    cx;
  68.     WORD    cy;
  69. } DLGTEMPLATE, FAR *LPDLGTEMPLATE;
  70.  
  71. typedef struct {
  72.     WORD    x;
  73.     WORD    y;
  74.     WORD    cx;
  75.     WORD    cy;
  76.     WORD    id;
  77.     DWORD   style;
  78. } DLGITEMTEMPLATE, FAR *LPDLGITEMTEMPLATE;
  79.  
  80. #pragma pack()
  81. #endif  /* !WIN32 */
  82.  
  83. /*  Additional stuff for handling resources */
  84. #define cchMaxDlgString         256
  85.  
  86. #if defined(WIN16)
  87. #define CbDlgStrlen(_s)     Cbtszsize(_s)
  88. #elif defined (WIN32)
  89. #if defined (_WIN95)
  90. __inline int
  91. CbDlgStrlen (LPVOID _s)
  92. {
  93.     unsigned short *wp = _s;
  94.     while (*wp++) ;
  95.     return ((unsigned char *)wp - (unsigned char *)_s);
  96. }
  97. #else
  98. #define CbDlgStrlen(_s)     ((lstrlenW((LPWSTR)(_s))+1) * sizeof(WCHAR))
  99. #endif
  100. #endif
  101.  
  102. /*  Display table column set */
  103.  
  104. #define cColsDT         9
  105.  
  106. SizedSPropTagArray(cColsDT, ptaColsDT) =
  107. {
  108.     cColsDT,
  109.     {
  110.         PR_ROWID,
  111.         PR_XPOS,
  112.         PR_DELTAX,
  113.         PR_YPOS,
  114.         PR_DELTAY,
  115.         PR_CONTROL_TYPE,
  116.         PR_CONTROL_STRUCTURE,
  117.         PR_CONTROL_ID,
  118.         PR_CONTROL_FLAGS,
  119.     }
  120. };
  121.  
  122. /*  Local functions */
  123.  
  124. CALLERRELEASE       FreeDT;
  125. ULONG               CtltypeOfItem(LPDLGITEMTEMPLATE pitem);
  126.  
  127. /*
  128.  -  BuildDisplayTable
  129.  -
  130.  *  Purpose:
  131.  *      Creates a display table from a data structure consisting of
  132.  *      1) Windows resources with localizable strings and screen
  133.  *      positions; 2) mostly static data giving property interface
  134.  *      mappings for the fields to be displayed.
  135.  *
  136.  *  Arguments:
  137.  *      lpfAllocateBuffer   in      MAPI allocation family
  138.  *      lpfAllocateMore     in      ditto
  139.  *      lpfFreeBuffer       in      ditto
  140.  *      hInstance           in      instance of module to retrieve
  141.  *                                  the resources from
  142.  *      cPages              in      number of property sheets
  143.  *      lpPage              in      array of property sheet descriptions
  144.  *      ulFlags             in      MAPI_UNICODE
  145.  *      lppTable            out     the display table
  146.  *
  147.  *  Returns:
  148.  *      HRESULT
  149.  *
  150.  *  Errors:
  151.  *      out of memory, or invalid inputs
  152.  */
  153. HRESULT STDAPICALLTYPE BuildDisplayTable(
  154.     LPALLOCATEBUFFER    lpfAllocateBuffer,
  155.     LPALLOCATEMORE      lpfAllocateMore,
  156.     LPFREEBUFFER        lpfFreeBuffer,
  157.     LPMALLOC            lpMalloc,
  158.     HINSTANCE           hInstance,
  159.     UINT                cPages,
  160.     LPDTPAGE            lpPage,
  161.     ULONG               ulFlags,
  162.     LPMAPITABLE *       lppTable,
  163.     LPTABLEDATA *       lppTblData)
  164. {
  165.     HRESULT         hr;
  166.     SCODE           sc;
  167.     LPTABLEDATA     ptad = NULL;
  168.     SSortOrderSet   so = { 0 };
  169.     LPSPropValue    rgprop = NULL;
  170.     LPSPropValue    pprop;
  171.     UINT            iPage;
  172.     UINT            ictl;
  173.     LPDTCTL         pctl;
  174.     ULONG           irow = 0L;
  175.     SRow            row;
  176.     UINT            cbText;
  177.     UINT            cb;
  178.     LPVOID          pv;
  179.     LPDLGTEMPLATE   pdlg;
  180.     TCHAR           szText[cchMaxDlgString+1];
  181.  
  182. #ifdef  PARAMETER_VALIDATION
  183.     Assert(cPages);
  184.     AssertSz( !lpfAllocateBuffer || !IsBadCodePtr( FARPROC( lpfAllocateBuffer ),
  185.             "lpfAllocateBuffer fails address check" );
  186.             
  187.     AssertSz( !lpfAllocateMore || !IsBadCodePtr( FARPROC( lpfAllocateMore ),
  188.             "lpfAllocateMore fails address check" );
  189.     
  190.     AssertSz( !lpfFreeBuffer || !IsBadCodePtr( FARPROC( lpfFreeBuffer ),
  191.             "lpfFreeBuffer fails address check" );
  192.     
  193. #ifdef  DEBUG
  194.     if (lpMalloc)
  195.         DebugTrace("BuildDisplayTable: lpMalloc is unused, pass NULL\n");
  196. #endif  
  197.             
  198.     if (IsBadReadPtr(lpPage, cPages*sizeof(DTPAGE)))
  199.     {
  200.         DebugTraceArg(BuildDisplayTable, "lpPage fails address check");
  201.         return ResultFromScode(E_INVALIDARG);
  202.     }
  203.     /*  Detailed validation of individual structures happens further down */
  204.     if (IsBadWritePtr(lppTable, sizeof(LPMAPITABLE)))
  205.     {
  206.         DebugTraceArg(BuildDisplayTable, "lppTable fails address check");
  207.         return ResultFromScode(E_INVALIDARG);
  208.     }
  209.  
  210.     /*  Detailed validation of individual structures happens further down */
  211.     if (lpTblData && IsBadWritePtr(lppTblData, sizeof(LPTABLEDATA)))
  212.     {
  213.         DebugTraceArg(BuildDisplayTable, "lppTblData fails address check");
  214.         return ResultFromScode(E_INVALIDARG);
  215.     }
  216.  
  217. #endif  /* PARAMETER_VALIDATION */
  218.  
  219.     *lppTable = NULL;
  220.  
  221.     /*  Create the table data object */
  222.     if (FAILED(sc = CreateTable((LPIID)&IID_IMAPITableData, lpfAllocateBuffer,
  223.         lpfAllocateMore, lpfFreeBuffer, NULL, TBLTYPE_SNAPSHOT, PR_ROWID,
  224.             (LPSPropTagArray)&ptaColsDT, &ptad)))
  225.     {
  226.         DebugTrace("BuildDisplayTable:  Can't create IMAPITableData");
  227.         goto retSc;
  228.     }
  229.     MAPISetBufferName(ptad, "Display Table TAD Object");
  230.  
  231.     /*  Loop over pages */
  232.     for (iPage = 1; iPage <= cPages; ++iPage, ++lpPage)
  233.     {
  234.         HRSRC       hrsrc;
  235.         HGLOBAL     hglobal = 0;
  236.         LPBYTE      pb = NULL;
  237.         LPDLGITEMTEMPLATE pitem;
  238.  
  239. #ifdef  PARAMETER_VALIDATION
  240.         if (lpPage->cctl == 0 ||
  241.             IsBadReadPtr(lpPage, sizeof(DTPAGE)) ||
  242.             IsBadReadPtr(lpPage->lpctl, lpPage->cctl * sizeof(DTCTL)))
  243.         {
  244.             DebugTrace("BuildDisplayTable: page %d fails address check\n", iPage);
  245.             goto badArg;
  246.         }
  247. #endif  /* PARAMETER_VALIDATION */
  248.  
  249.         /*  Load the resource for this page */
  250.         if (!(hrsrc = FindResource(hInstance, lpPage->lpszResourceName, RT_DIALOG))
  251.             || !(hglobal = LoadResource(hInstance, hrsrc))
  252.             || !(pb = LockResource(hglobal)))
  253.         {
  254.             DebugTrace("BuildDisplayTable: failed to load resource on page %d\n", iPage);
  255.             goto badArg;
  256.         }
  257.  
  258.         /*  Validate the dialog template */
  259.         pdlg = (LPDLGTEMPLATE)pb;
  260.         Assert(lpPage->cctl == (UINT)pdlg->cdit || lpPage->cctl == (UINT)pdlg->cdit + 1);
  261.         /* //$  more validation? */
  262.  
  263.         /*  Skip pb to the first dialog item template */
  264.         pb += sizeof(DLGTEMPLATE);  /*  skip header */
  265.         pb += CbDlgStrlen(pb);      /*  skip menu name */
  266.         pb += CbDlgStrlen(pb);      /*  skip class name */
  267.                                     /*  copy dialog caption to right charset */
  268. #if !defined(UNICODE) && defined(WIN32) /* && defined(_WINNT) */
  269.         cbText = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)pb, -1,
  270.             szText, sizeof(szText), NULL, NULL);
  271.         if (!cbText)
  272.         {
  273.             DebugTrace("BuildDisplayTable: failed to convert Unicode (%ld)\n", GetLastError());
  274.             sc = E_FAIL;
  275.             goto retSc;
  276.         }
  277. #else
  278.         cbText = CbDlgStrlen(pb);
  279.         MemCopy(szText, pb, min(cbText, sizeof(szText)));
  280.         szText[cchMaxDlgString] = 0;
  281. #endif
  282.         pb += CbDlgStrlen(pb);      /*  ...and skip dialog caption */
  283.         if (pdlg->style & DS_SETFONT)
  284.         {
  285.             pb += sizeof(short int);    /*  skip point size */
  286.             pb += CbDlgStrlen(pb);      /*  skip typeface name */
  287.         }
  288. #if defined(WIN32) /* && defined(_WINNT) */
  289.         if ((ULONG)pb % 4)          /*  Skip to 4-byte boundary */
  290.             pb += 2;
  291.         Assert(((ULONG)pb % 4) == 0);
  292. #endif
  293.  
  294.         /*  Properties for the New Page control, which must come first */
  295.         /*  if it is there at all, are obtained from the dialog. */
  296.         if (lpPage->cctl && lpPage->lpctl[0].ulCtlType == DTCT_PAGE)
  297.         {
  298.             SPropValue  rgpropT[9];
  299.             BYTE        rgb[100];
  300.             TCHAR       szComponent[cchMaxDlgString+1];
  301.             LPTSTR      lpszComponent = szComponent;
  302.             ULONG       cbComponent;
  303.  
  304.             /*
  305.              *  If not already passed in, get the string associated with
  306.              *  the szComponent from resources
  307.              */
  308.  
  309.             if (!(lpPage->ulItemID & 0xFFFF0000))
  310.             {
  311. #if defined(WIN32) && !defined(_MAC)
  312.                 if (lpPage->lpctl[0].ulCtlFlags & MAPI_UNICODE)
  313.                 {
  314.                     LoadStringW(hInstance,
  315.                         (UINT) lpPage->ulItemID,
  316.                         (LPWSTR) lpszComponent,
  317.                         cchMaxDlgString);
  318.                 } else
  319. #endif /* defined(WIN32) */
  320.                 {
  321.                     LoadStringA(hInstance, 
  322.                         (UINT) lpPage->ulItemID,
  323.                         (LPSTR) lpszComponent,
  324.                         cchMaxDlgString);
  325.                 }
  326.             } else
  327.             {
  328.                 lpszComponent = lpPage->lpszComponent;
  329.             }
  330.  
  331.             /*  Row ID */
  332.             rgpropT[0].ulPropTag = PR_ROWID;
  333.             rgpropT[0].Value.ul = irow++;
  334.  
  335.             /*  No coordinates for page */
  336.  
  337.             /*  Control type */
  338.             rgpropT[1].ulPropTag = PR_CONTROL_TYPE;
  339.             rgpropT[1].Value.l = DTCT_PAGE;
  340.  
  341.             /*  Control flags */
  342.             rgpropT[2].ulPropTag = PR_CONTROL_FLAGS;
  343.             rgpropT[2].Value.l = lpPage->lpctl[0].ulCtlFlags;
  344.  
  345.             /*  Control structure */
  346.             memset(rgb, 0, sizeof(rgb));
  347.             rgpropT[3].ulPropTag = PR_CONTROL_STRUCTURE;
  348.             if (!szText[0])
  349.             {
  350.                 SideAssert(LoadStringA(HinstMapi(), IDS_GeneralPage, szText,
  351.                     cchMaxDlgString));
  352.             }
  353.  
  354.             cbText = min(Cbtszsize(szText), sizeof(rgb)-sizeof(DTBLPAGE)-1);
  355.             MemCopy(rgb+sizeof(DTBLPAGE), szText, cbText);
  356.  
  357.             ((LPDTBLPAGE)rgb)->ulbLpszLabel = sizeof(DTBLPAGE);
  358.             ((LPDTBLPAGE)rgb)->ulFlags = lpPage->lpctl[0].ctl.lppage->ulFlags;
  359.  
  360.             ((LPDTBLPAGE)rgb)->ulbLpszComponent = sizeof(DTBLPAGE)+cbText;
  361.             cbComponent = min(Cbtszsize(lpszComponent), sizeof(rgb)-sizeof(DTBLPAGE)-cbText-1);
  362.             MemCopy(rgb+sizeof(DTBLPAGE)+cbText, lpszComponent, cbComponent);
  363.             ((LPDTBLPAGE)rgb)->ulContext = lpPage->lpctl[0].ctl.lppage->ulContext;
  364.  
  365.             rgpropT[3].Value.bin.cb = sizeof(DTBLPAGE) + cbText + cbComponent;
  366.             rgpropT[3].Value.bin.lpb = rgb;
  367.  
  368.             /* Control notification. */
  369.             rgpropT[4].ulPropTag     = PR_CONTROL_ID;
  370.             rgpropT[4].Value.bin.lpb = lpPage->lpctl[0].lpbNotif;
  371.             rgpropT[4].Value.bin.cb  = lpPage->lpctl[0].cbNotif;
  372.  
  373.             /* X-Y position, X-Y delta */
  374.             rgpropT[5].ulPropTag     = PR_XPOS;
  375.             rgpropT[5].Value.l = 0;
  376.             rgpropT[6].ulPropTag     = PR_DELTAX;
  377.             rgpropT[6].Value.l = 0;
  378.  
  379.             rgpropT[7].ulPropTag     = PR_YPOS;
  380.             rgpropT[7].Value.l = 0;
  381.             rgpropT[8].ulPropTag     = PR_DELTAY;
  382.             rgpropT[8].Value.l = 0;
  383.  
  384.             /*  Pop the row in */
  385.             row.cValues = 9;
  386.             row.lpProps = rgpropT;
  387.             if (HR_FAILED(hr = ptad->lpVtbl->HrModifyRow(ptad, &row)))
  388.                 goto ret;
  389.  
  390.             /*  We've already processed the first control */
  391.             ictl = 2;
  392.         }
  393.         else
  394.             /*  Begin with the first control */
  395.             ictl = 1;
  396.  
  397.         /*  Loop over remaining controls on this page */
  398.         for (pctl = lpPage->lpctl+ictl-1; ictl<= lpPage->cctl; ++ictl, ++pctl)
  399.         {
  400.             /*  Build the display table columns for this row */
  401.             if (FAILED(sc = (*lpfAllocateBuffer)(cColsDT*sizeof(SPropValue),
  402.                     (LPVOID FAR *)&rgprop)))
  403.                 goto retSc;
  404.             pprop = rgprop;
  405.  
  406.             /*  Remember the control text for this item (if any), and */
  407.             /*  advance the pointer to the next dialog item. */
  408.             pitem = (LPDLGITEMTEMPLATE)pb;
  409.             pb += sizeof(DLGITEMTEMPLATE);      /*  point to control type */
  410. #if defined(WIN16)
  411.             if (*pb & 0x80)
  412.                 ++pb;
  413.             else
  414.                 pb += CbDlgStrlen(pb);          /*  skip to item text */
  415. #elif defined(WIN32) /* && defined(_WINNT) */
  416.             if (*((WORD *)pb) == 0xffff)
  417.                 pb += 4;
  418.             else
  419.                 pb += CbDlgStrlen(pb);
  420. #endif
  421.  
  422. #if !defined(UNICODE) && defined(WIN32) /* && defined(_WINNT) */
  423.             /*  Copy item text to szText */
  424.             cbText = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)pb, -1,
  425.                 szText, sizeof(szText), NULL, NULL);
  426.             if (!cbText)
  427.             {
  428.                 DebugTrace("BuildDisplayTable: failed to convert Unicode (%ld)\n", GetLastError());
  429.                 sc = E_FAIL;
  430.                 goto retSc;
  431.             }
  432. #else
  433.             cbText = CbDlgStrlen(pb);
  434.             MemCopy(szText, pb, min(cbText, sizeof(szText)));
  435.             szText[cchMaxDlgString] = 0;
  436. #endif
  437.  
  438. #if defined(WIN16)
  439.             pb += CbDlgStrlen(pb);              /*  skip the item text */
  440. #elif defined(WIN32) /* && defined(_WINNT) */
  441.             if (*((WORD *)pb) == 0xffff)
  442.                 pb += 4;
  443.             else
  444.                 pb += CbDlgStrlen(pb);
  445. #endif
  446. #ifdef  WIN16
  447.             pb += *pb + 1;                      /*  Skip extra info. */
  448. #elif defined(WIN32) /* && defined(_WINNT) */
  449.             if ((ULONG)pb % 4)                  /*  Skip creation data. */
  450.                 pb += 2;
  451.             else
  452.                 pb += 4;
  453.             Assert(((ULONG)pb % 4) == 0);
  454. #endif
  455.  
  456.             /*  Validations */
  457.             if (pctl->ulItemID != pitem->id)
  458.             {
  459.                 DebugTrace("BuildDisplayTable: item ID mismatch, dtct ID %ld, resource ID %ld, page %d, line %d\n"
  460.                           , pctl->ulItemID, pitem->id, iPage, ictl);
  461.                 goto badArg;
  462.             }
  463.             if (pctl->ulCtlType != CtltypeOfItem(pitem))
  464.             {
  465.                 DebugTrace("BuildDisplayTable: control type mismatch, dtct ID %ld, page %d, line %d\n"
  466.                           , pctl->ulItemID, iPage, ictl);
  467.                 goto badArg;
  468.             }
  469.             if (pctl->ulCtlFlags & ~(DT_MULTILINE | DT_EDITABLE |
  470.                 DT_REQUIRED | DT_SET_IMMEDIATE | DT_PASSWORD_EDIT |
  471.                 DT_ACCEPT_DBCS | DT_SET_SELECTION))
  472.             {
  473.                 DebugTrace("BuildDisplayTable: unknown control flags, dtct ID %ld, page %d, line %d\n"
  474.                           , pctl->ulItemID, iPage, ictl);
  475.                 goto badArg;
  476.             }
  477.  
  478.             /*  row ID */
  479.             pprop->ulPropTag = PR_ROWID;
  480.             pprop->Value.ul = irow++;
  481.             ++pprop;
  482.  
  483.             /*  Coordinates */
  484.             pprop->ulPropTag = PR_XPOS;
  485.             pprop->Value.l = pitem->x;
  486.             ++pprop;
  487.             pprop->ulPropTag = PR_DELTAX;
  488.             pprop->Value.l = pitem->cx;
  489.             ++pprop;
  490.             pprop->ulPropTag = PR_YPOS;
  491.             pprop->Value.l = pitem->y;
  492.             ++pprop;
  493.             pprop->ulPropTag = PR_DELTAY;
  494.             pprop->Value.l = pitem->cy;
  495.             ++pprop;
  496.  
  497.             /*  Control type */
  498.             pprop->ulPropTag = PR_CONTROL_TYPE;
  499.             pprop->Value.l = (long)pctl->ulCtlType;
  500.             ++pprop;
  501.  
  502.             /* Control notification. */
  503.             pprop->ulPropTag     = PR_CONTROL_ID;
  504.             pprop->Value.bin.lpb = pctl->lpbNotif;
  505.             pprop->Value.bin.cb  = pctl->cbNotif;
  506.             ++pprop;
  507.  
  508.             /*  Control flags.  */
  509.             pprop->ulPropTag = PR_CONTROL_FLAGS;
  510.             pprop->Value.l = pctl->ulCtlFlags;
  511.             ++pprop;
  512.  
  513.  
  514.  
  515.             /*  Control structure, which depends on the type. */
  516.             /*  In the switch we set up 'cb' the structure size and */
  517.             /*  'pv' the memory for the structure; common code puts */
  518.             /*  them into the prop value array. */
  519.  
  520.             cb = 0;
  521.             pv = NULL;
  522.  
  523.             switch ((short)pctl->ulCtlType)
  524.             {
  525.             case DTCT_LABEL:
  526.             {
  527. #define plabel  ((LPDTBLLABEL)pv)
  528.  
  529.                 /*  Text from the dialog item template becomes the */
  530.                 /*  label text (required). */
  531.                 cb = sizeof(DTBLLABEL) + cbText;
  532.                 if (FAILED(sc = (*lpfAllocateMore)(cb, rgprop, &pv)))
  533.                     goto retSc;
  534.                 *plabel = *(pctl->ctl.lplabel);
  535.                 Assert(plabel->ulbLpszLabelName == sizeof(DTBLLABEL));
  536.                 MemCopy(plabel+1, szText, cbText);
  537.                 break;
  538. #undef plabel
  539.             }
  540.  
  541.             case DTCT_EDIT:
  542.             {
  543. #define pedit   ((LPDTBLEDIT)pv)
  544.  
  545.                 /*  The required filter string comes with the structure, */
  546.                 /*  NOT from the dialog template. Text from the dialog */
  547.                 /*  template is IGNORED; any initial value for the edit */
  548.                 /*  comes from the property interface. */
  549.                 cb = sizeof(DTBLEDIT) + Cbtszsize(pctl->lpszFilter);
  550.                 if (FAILED(sc = (*lpfAllocateMore)(cb, rgprop, &pv)))
  551.                     goto retSc;
  552.                 MemCopy(pedit, pctl->ctl.lpedit, sizeof(DTBLEDIT));
  553.                 lstrcpy((LPTSTR)(pedit+1), pctl->lpszFilter);
  554.                 Assert(pedit->ulbLpszCharsAllowed = sizeof(DTBLEDIT));
  555.                 break;
  556. #undef pedit
  557.             }
  558.  
  559.             case DTCT_LBX:
  560.             {
  561. #define plbx    ((LPDTBLLBX)pv)
  562.  
  563.                 /*  No text */
  564.                 cb = sizeof(DTBLLBX);
  565.                 if (FAILED(sc = (*lpfAllocateMore)(cb, rgprop, &pv)))
  566.                     goto retSc;
  567.                 *plbx = *(pctl->ctl.lplbx);
  568.                 break;
  569. #undef plbx
  570.             }
  571.  
  572.             case DTCT_COMBOBOX:
  573.             {
  574. #define pcombobox   ((LPDTBLCOMBOBOX)pv)
  575.                 /*  Filter string as for an edit */
  576.                 /*  Dialog template text is IGNORED */
  577.                 cb = sizeof(DTBLCOMBOBOX) + Cbtszsize(pctl->lpszFilter);
  578.                 if (FAILED(sc = (*lpfAllocateMore)(cb, rgprop, &pv)))
  579.                     goto retSc;
  580.                 MemCopy(pcombobox, pctl->ctl.lpcombobox, sizeof(DTBLCOMBOBOX));
  581.                 lstrcpy((LPTSTR)(pcombobox+1), pctl->lpszFilter);
  582.                 Assert(pcombobox->ulbLpszCharsAllowed == sizeof(DTBLCOMBOBOX));
  583.                 break;
  584. #undef pcombobox
  585.             }
  586.  
  587.             case DTCT_DDLBX:
  588.             {
  589. #define pddlbx  ((LPDTBLDDLBX)pv)
  590.                 /*  No text or other extra data */
  591.                 cb = sizeof(DTBLDDLBX);
  592.                 if (FAILED(sc = (*lpfAllocateMore)(cb, rgprop, &pv)))
  593.                     goto retSc;
  594.                 *pddlbx = *(pctl->ctl.lpddlbx);
  595.                 break;
  596. #undef pddlbx
  597.             }
  598.  
  599.             case DTCT_CHECKBOX:
  600.             {
  601. #define pcheckbox   ((LPDTBLCHECKBOX)pv)
  602.                 /*  Text from the dialog item template is the label */
  603.                 cb = sizeof(DTBLCHECKBOX) + cbText;
  604.                 if (FAILED(sc = (*lpfAllocateMore)(cb, rgprop, &pv)))
  605.                     goto retSc;
  606.                 *pcheckbox = *(pctl->ctl.lpcheckbox);
  607.                 MemCopy(pcheckbox+1, szText, cbText);
  608.                 pcheckbox->ulbLpszLabel = sizeof(DTBLCHECKBOX);
  609.                 break;
  610. #undef pcheckbox
  611.             }
  612.  
  613.             case DTCT_GROUPBOX:
  614.             {
  615. #define pgroupbox   ((LPDTBLGROUPBOX)pv)
  616.                 /*  Text from the dialog item template becomes the label */
  617.                 cb = sizeof(DTBLGROUPBOX) + cbText;
  618.                 if (FAILED(sc = (*lpfAllocateMore)(cb, rgprop, &pv)))
  619.                     goto retSc;
  620.                 *pgroupbox = *(pctl->ctl.lpgroupbox);
  621.                 MemCopy(pgroupbox+1, szText, cbText);
  622.                 pgroupbox->ulbLpszLabel = sizeof(DTBLGROUPBOX);
  623.                 break;
  624. #undef pgroupbox
  625.             }
  626.  
  627.             case DTCT_BUTTON:
  628.             {
  629. #define pbutton ((LPDTBLBUTTON)pv)
  630.                 /*  Text from the dialog item template is the label */
  631.                 cb = sizeof(DTBLBUTTON) + cbText;
  632.                 if (FAILED(sc = (*lpfAllocateMore)(cb, rgprop, &pv)))
  633.                     goto retSc;
  634.                 *pbutton = *(pctl->ctl.lpbutton);
  635.                 MemCopy(pbutton+1, szText, cbText);
  636.                 pbutton->ulbLpszLabel = sizeof(DTBLBUTTON);
  637.                 break;
  638. #undef pbutton
  639.             }
  640.  
  641.             case DTCT_RADIOBUTTON:
  642.             {
  643. #define pradio  ((LPDTBLRADIOBUTTON)pv)
  644.                 /*  Text from the dialog item template is the label */
  645.                 cb = sizeof(DTBLRADIOBUTTON) + cbText;
  646.                 if (FAILED(sc = (*lpfAllocateMore)(cb, rgprop, &pv)))
  647.                     goto retSc;
  648.                 *pradio = *(pctl->ctl.lpradiobutton);
  649.                 MemCopy(pradio+1, szText, cbText);
  650.                 pradio->ulbLpszLabel = sizeof(DTBLRADIOBUTTON);
  651.                 break;
  652. #undef pradio
  653.             }
  654.  
  655.             case DTCT_MVLISTBOX:
  656.             {
  657. #define pmvlbx  ((LPDTBLMVLISTBOX)pv)
  658.                 /*  No text or other extra data */
  659.                 cb = sizeof(DTBLMVLISTBOX);
  660.                 if (FAILED(sc = (*lpfAllocateMore)(cb, rgprop, &pv)))
  661.                     goto retSc;
  662.                 *pmvlbx = *(pctl->ctl.lpmvlbx);
  663.                 break;
  664. #undef pmvlbx
  665.             }
  666.  
  667.             case DTCT_MVDDLBX:
  668.             {
  669. #define pmvddlbx    ((LPDTBLMVDDLBX)pv)
  670.                 /*  No text or other extra data */
  671.                 cb = sizeof(DTBLMVDDLBX);
  672.                 if (FAILED(sc = (*lpfAllocateMore)(cb, rgprop, &pv)))
  673.                     goto retSc;
  674.                 *pmvddlbx = *(pctl->ctl.lpmvddlbx);
  675.                 break;
  676. #undef pmvddlbx
  677.             }
  678.  
  679.             case DTCT_PAGE:
  680.                 /*  Shouldn't see this, fall into default case */
  681.  
  682.             default:
  683.                 AssertSz(FALSE, "Invalid Control Type in BuildDisplayTable");
  684.                 break;
  685.             }
  686.  
  687.             pprop->ulPropTag = PR_CONTROL_STRUCTURE;
  688.             pprop->Value.bin.cb = cb;
  689.             pprop->Value.bin.lpb = pv;
  690.             ++pprop;
  691.  
  692.             /*  Add the new line to the display table */
  693.             row.cValues = pprop - rgprop;
  694.             row.lpProps = rgprop;
  695.             if (HR_FAILED(hr = ptad->lpVtbl->HrModifyRow(ptad, &row)))
  696.                 goto ret;
  697.  
  698. /*cleanupLine: */
  699.             (*lpfFreeBuffer)(rgprop);
  700.             rgprop = NULL;
  701.         }
  702.  
  703. /*cleanupPage: */
  704.         if (hglobal)
  705.         {
  706.             if (pb)
  707.             {
  708.                 UnlockResource(hglobal);
  709.                 pb = NULL;
  710.             }
  711.             FreeResource(hglobal);
  712.             hglobal = 0;
  713.         }
  714.     }
  715.  
  716.     /*  Get a view on the table data and return it */
  717.     if (lppTblData==NULL)
  718.         hr = ptad->lpVtbl->HrGetView(ptad, &so, FreeDT, (ULONG)ptad, lppTable);
  719.     else
  720.         hr = ptad->lpVtbl->HrGetView(ptad, &so, NULL, (ULONG)ptad, lppTable);
  721.  
  722.     #ifdef DEBUG
  723.     if (hr == hrSuccess)
  724.     {
  725.         MAPISetBufferName(*lppTable, "Display Table View Object");
  726.     }
  727.     #endif
  728.  
  729.     /*  ...and fall through */
  730.  
  731. ret:
  732.     (*lpfFreeBuffer)(rgprop);
  733.     if (HR_FAILED(hr))
  734.     {
  735.         if (ptad)
  736.             ptad->lpVtbl->Release(ptad);
  737.     }
  738.     else if (lppTblData)
  739.     {
  740.         *lppTblData=ptad;
  741.     }
  742.  
  743.     DebugTraceResult(BuildDisplayTable, hr);
  744.     return hr;
  745.  
  746. retSc:
  747.     hr = ResultFromScode(sc);
  748.     goto ret;
  749.  
  750. badArg:
  751.     hr = ResultFromScode(E_INVALIDARG);
  752.     goto ret;
  753. }
  754.  
  755. void STDAPICALLTYPE
  756. FreeDT(ULONG ulCallerData, LPTABLEDATA ptad, LPMAPITABLE ptable)
  757. {
  758.     Assert(ulCallerData == (ULONG)ptad);
  759.     ptad->lpVtbl->Release(ptad);
  760. }
  761.  
  762. ULONG
  763. CtltypeOfItem(LPDLGITEMTEMPLATE pitem)
  764. {
  765.     LPTSTR  szClass = (LPTSTR)(pitem+1);
  766.     WORD    wClass = 0xffff;
  767.     BYTE    bStyle = (BYTE)pitem->style;
  768.  
  769.     /*  Not making the 0xffff stuff platform-specific is a little cheesy, */
  770.     /*  but we're going to get away with it because we only support */
  771.     /*  the standard control types, which should never appear as */
  772.     /*  Unicode strings. */
  773.  
  774.     /*  First figure out the basic control type. */
  775. #ifdef WIN16
  776.     if (*((LPBYTE)szClass) & 0x80)
  777.         wClass = *((LPBYTE)szClass);
  778. #endif
  779. #if defined(WIN32)  /*  && defined(_WINNT) */
  780.     if (*((WORD *)szClass) == 0xffff)
  781.         wClass = ((WORD *)szClass)[1];
  782. #endif
  783.     else
  784.     {
  785.         if (!lstrcmpi(szClass, "BUTTON"))
  786.             wClass = 0x0080;
  787.         else if (!lstrcmpi(szClass, "EDIT"))
  788.             wClass = 0x0081;
  789.         else if (!lstrcmpi(szClass, "STATIC"))
  790.             wClass = 0x0082;
  791.         else if (!lstrcmpi(szClass, "LISTBOX"))
  792.             wClass = 0x0083;
  793.         else if (!lstrcmpi(szClass, "COMBOBOX"))
  794.             wClass = 0x0085;
  795.     }
  796.  
  797.     /*  Next, figure out the subtype based on style bits. */
  798.     if (wClass == 0x0080)
  799.     {
  800.         if (bStyle == BS_PUSHBUTTON || bStyle == BS_DEFPUSHBUTTON)
  801.             return DTCT_BUTTON;
  802.         else if (bStyle == BS_RADIOBUTTON || bStyle == BS_AUTORADIOBUTTON)
  803.             return DTCT_RADIOBUTTON;
  804.         else if (bStyle == BS_CHECKBOX || bStyle == BS_AUTOCHECKBOX)
  805.             return DTCT_CHECKBOX;
  806.         else if (bStyle == BS_GROUPBOX)
  807.             return DTCT_GROUPBOX;
  808.         else
  809.             return 0xffffffff;
  810.     }
  811.     else if (wClass == 0x0081)
  812.         return DTCT_EDIT;
  813.     else if (wClass == 0x0082)
  814.         return DTCT_LABEL;
  815.     else if (wClass == 0x0083)
  816.         return DTCT_LBX;
  817.     else if (wClass == 0x0085)
  818.     {
  819.         if (bStyle == CBS_DROPDOWN || bStyle == CBS_DROPDOWNLIST)
  820.             return DTCT_DDLBX;
  821.         return DTCT_COMBOBOX;
  822.     }
  823.  
  824.     /*  Not one of ours. */
  825.     return 0xffffffff;
  826. }
  827.