home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / os2sdk / os2sdk12 / ddeml / dmghsz.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-22  |  15.7 KB  |  597 lines

  1. /****************************** Module Header ******************************\
  2. * Module Name: DMGLATOM.C
  3. *
  4. * This module contains functions used for HSZ control.
  5. *
  6. * Created:  8/2/88    sanfords
  7. * Added case preservation/insensitive   1/22/90       Sanfords
  8. * 6/12/90 sanfords  Fixed HSZ local string allocation size errors.
  9. *                   Added latom validation checks
  10. *
  11. * Copyright (c) 1988, 1989  Microsoft Corporation
  12. \***************************************************************************/
  13. #include "ddemlp.h"
  14.  
  15.  
  16. /*
  17.  * since the top 12 bits of any latom is always 0 (unless we have > 16
  18.  * atom tables!) we can encode any ulong into only 5 bytes.
  19.  */
  20. #define ENCODEBYTES         5
  21. #define MAX_LATOMSTRSIZE    255 - ENCODEBYTES - 2
  22. char szT[MAX_LATOMSTRSIZE + 1 + ENCODEBYTES];  /* used for HSZ expansion */
  23.  
  24. extern BOOL APIENTRY WinSetAtomTableOwner( HATOMTBL, PID );
  25.  
  26.  
  27. /*********************** LATOM management functions *************************\
  28. * An HSZ is a long atom which holds an encoded reference to two other long
  29. * atoms.  One long atom is for the actual string, the other is for its
  30. * uppercase version.  Two HSZs are ranked by their uppercase latoms.
  31. * This makes HSZs case insensitive, case preserving.  An latom
  32. * is an atom with an atom table index tacked onto the HIUSHORT part of 
  33. * of the latom.  Strings too long for the atom manager are split up and
  34. * each piece is prepended with a coded string that represents the
  35. * LATOM of the rest of the string.  LATOM strings thus may be of any length.
  36. * (up to 64K in this version)
  37. *
  38. * History:
  39. *   Created     9/12/89    Sanfords
  40. \***************************************************************************/
  41.  
  42. /***************************** Private Function ****************************\
  43. * Allocates space in the DDE manager heap for a string queried from the DDE
  44. * manager latomtable.  The case sensitive string is returned.
  45. *
  46. * This function should be serialized.  Memory allocation or latom table failure
  47. * results in a 0 return value.
  48. *
  49. * 0 latoms result in a NULL terminated empty string.
  50. *
  51. * Note that *pcch is set to the length of the string INCLUDING the null
  52. * terminator.  This way a wild string has a cch=1.
  53. *
  54. * History:
  55. *   created     12/22/88        sanfords
  56. *   11/10/89    sanfords        modified to return '\0' on invalid atom.
  57. \***************************************************************************/
  58. PSZ pszFromHsz(hsz, pcch)
  59. HSZ hsz;
  60. USHORT FAR *pcch;
  61. {
  62.     PSZ psz;
  63.     LATOM latom;
  64.     char sz[ENCODEBYTES + 1];
  65.     register USHORT cch;
  66.  
  67.     SemCheckIn();
  68.  
  69.     if (hsz == 0)
  70.         cch = 1;
  71.     else {
  72.         QuerylatomName((LATOM)hsz, sz, ENCODEBYTES + 1);
  73.         latom = Decode(sz);     /* take origonal case version */
  74.         cch = QuerylatomLength(latom) + 1;
  75.     }
  76.      
  77.     psz = (PSZ)FarAllocMem(hheapDmg, cch);
  78.     if (psz == 0) {
  79.         *pcch = '\000';
  80.         return(0);
  81.     }
  82.  
  83.     if (hsz == 0) {
  84.         *pcch = 1;
  85.         *psz = '\0';
  86.     } else {
  87.         *pcch = cch;
  88.         if (QuerylatomName(latom, psz, cch) == 0) {
  89.             AssertF(FALSE, "pszFromHsz - bad latom");
  90.             *psz = '\0';        /* invalid case - never expected */
  91.         }
  92.     }
  93.     return(psz);
  94. }
  95.  
  96.  
  97. /***************************** Private Function ****************************\
  98. * HSZ GetHsz(psz, cc, cp, fAdd)
  99. * PSZ psz;
  100. * USHORT cc;
  101. * USHORT cp;
  102. * BOOL fAdd;
  103. *
  104. * The goal of this routine is to convert a psz to an hsz.  This uses the
  105. * atom manager for its dirty work.  This call has the side effect of
  106. * incrementing the use count for the hsz returned and its associated latoms
  107. * if fAdd is set.
  108. *
  109. * if fAdd is FALSE, NULL is returned if the hsz doesn't exist.
  110. *
  111. * History:
  112. *   created     12/23/88    sanfords
  113. \***************************************************************************/
  114. HSZ GetHsz(psz, cc, cp, fAdd)
  115. PSZ psz;
  116. USHORT cc;
  117. USHORT cp;
  118. BOOL fAdd;
  119. {
  120.     LATOM latom1, latom2;
  121.     USHORT cb;
  122.     PSZ pszT;
  123.     BOOL fNew = FALSE;
  124.     HSZ hsz;
  125.  
  126.     /*
  127.      * NULL or 0 length pszs are considered wild HSZs.
  128.      */
  129.     if (psz == NULL || *psz == '\0')
  130.         return(0L);
  131.  
  132.     SemEnter();
  133.     
  134.     if (!(latom1 = FindAddlatom(psz, fAdd))) {
  135.         AssertF(!fAdd, "GetHsz - Atom Add failed");
  136.         SemLeave();
  137.         return(0L);
  138.     }
  139.         
  140.     cb = lstrlen(psz) + 1;
  141.         
  142.     if (!(pszT = FarAllocMem(hheapDmg, max(cb, ENCODEBYTES * 2 + 1)))) {
  143.         SemLeave();
  144.         return(0L);
  145.     }
  146.     
  147.     CopyBlock((PBYTE)psz, (PBYTE)pszT, cb);
  148.     WinUpper(DMGHAB, cp ? cp : syscc.codepage, cc ? cc : syscc.country, pszT);
  149.     latom2 = FindAddlatom(pszT, fAdd);
  150.  
  151.     if (!latom2) {
  152.         AssertF(!fAdd, "GetHsz - Atom Add(2) failed");
  153.         hsz = 0;
  154.     } else {
  155.         *Encode(latom2, Encode(latom1, pszT)) = '\000';
  156.         hsz = (HSZ)FindAddlatom(pszT, fAdd);
  157.     }
  158.     FarFreeMem(hheapDmg, pszT, max(cb, ENCODEBYTES * 2 + 1));
  159.     SemLeave();
  160.     return(hsz);
  161. }
  162.  
  163.  
  164.  
  165. /*
  166.  * Note that all three associated latoms are freed.
  167.  */
  168. BOOL FreeHsz(hsz)
  169. HSZ hsz;
  170. {
  171.     char sz[ENCODEBYTES * 2 + 1];
  172.  
  173.     SemEnter();    
  174.     if (hsz && QuerylatomName((LATOM)hsz, sz, ENCODEBYTES * 2 + 1)) {
  175.         Freelatom(Decode((PBYTE)sz));
  176.         Freelatom(Decode((PBYTE)&sz[ENCODEBYTES]));
  177.         Freelatom((LATOM)hsz);
  178.     }
  179.     SemLeave();
  180.     return(TRUE);
  181. }
  182.     
  183.  
  184.  
  185. /*
  186.  * Note that all three associated latoms are incremented.  
  187.  */
  188. BOOL IncHszCount(hsz)
  189. HSZ hsz;
  190. {
  191.     char sz[ENCODEBYTES * 2 + 1];
  192.     register BOOL fRet;
  193.  
  194.     if (hsz == 0)
  195.         return(TRUE);
  196.         
  197.     SemEnter();
  198.     
  199.     QuerylatomName((LATOM)hsz, sz, ENCODEBYTES * 2 + 1);
  200.     fRet = InclatomCount(Decode((PBYTE)sz)) &&
  201.                 InclatomCount(Decode((PBYTE)&sz[ENCODEBYTES])) &&
  202.                 InclatomCount((LATOM)hsz);
  203.     SemLeave();
  204.     return(fRet);
  205. }
  206.  
  207.  
  208.  
  209. /***************************** Private Function ****************************\
  210. * This routine adds an atom table and returns its handle.  Returns fSuccess.
  211. *
  212. * Effects cAtbls, aAtbls, iAtblCurrent;
  213. *
  214. * History:
  215. *   Created     9/12/89    Sanfords
  216. \***************************************************************************/
  217. BOOL AddAtomTable(fInit)
  218. BOOL fInit;
  219. {
  220.     PHATOMTBL pat;
  221.  
  222.     SemEnter();    
  223.  
  224.     if (!(pat = (PHATOMTBL)FarAllocMem(hheapDmg,
  225.             sizeof(HATOMTBL) * (cAtbls + 1)))) {
  226.         SemLeave();
  227.         return(FALSE);
  228.     }
  229.     
  230.     if (!fInit) {
  231.         CopyBlock((PBYTE)aAtbls, (PBYTE)pat, sizeof(HATOMTBL) * cAtbls);
  232.         FarFreeMem(hheapDmg, aAtbls, sizeof(HATOMTBL) * cAtbls);
  233.     }
  234.     
  235.     aAtbls = pat;
  236.  
  237.     if (!(aAtbls[cAtbls] = WinCreateAtomTable(0, 0))) 
  238.         return(FALSE);
  239.     /*
  240.      * Share our atom tables with all processes...
  241.      */
  242.     if (!WinSetAtomTableOwner(aAtbls[cAtbls], NULL)) {
  243.         AssertF(FALSE, "AddAtomTable - WinSetAtomTable failed");
  244.         return(FALSE);
  245.     }
  246.     iAtblCurrent = cAtbls++;
  247.     SemLeave();
  248.     return(TRUE);
  249. }
  250.  
  251.  
  252.  
  253. USHORT QueryHszLength(hsz)
  254. HSZ hsz;
  255. {
  256.     char sz[ENCODEBYTES + 1];
  257.     USHORT us;
  258.  
  259.     if (!hsz) 
  260.         return(0);
  261.     SemEnter();
  262.     QuerylatomName((LATOM)hsz, sz, ENCODEBYTES + 1);
  263.     us = QuerylatomLength(Decode(sz));
  264.     SemLeave();
  265.     return(us);
  266. }
  267.  
  268.  
  269.  
  270. USHORT QueryHszName(hsz, psz, cchMax)
  271. HSZ hsz;
  272. PSZ psz;
  273. USHORT cchMax;
  274. {
  275.     char sz[ENCODEBYTES + 1];
  276.     register USHORT usRet;
  277.     
  278.     if (hsz == 0) {
  279.         if (psz)
  280.             *psz = '\000';
  281.         return(1);
  282.     } else {
  283.         usRet = 0;
  284.         SemEnter();
  285.         if (QuerylatomName((LATOM)hsz, sz, ENCODEBYTES + 1))
  286.             usRet = QuerylatomName(Decode(sz), psz, cchMax);
  287.         SemLeave();
  288.         return(usRet);
  289.     }
  290. }
  291.      
  292.  
  293.  
  294. /*
  295.  * returns 0 if ==, -1 if hsz1 < hsz2, 1 if hsz1 > hsz2, 2 on error
  296.  */
  297. SHORT CmpHsz(hsz1, hsz2)
  298. HSZ hsz1, hsz2;
  299. {
  300.     char sz[ENCODEBYTES * 2 + 1];
  301.     LATOM latom;
  302.     SHORT usRet;
  303.     
  304.     if (hsz1 == hsz2)
  305.         return(0);
  306.     if (!hsz1) 
  307.         return(-1);
  308.     if (!hsz2)
  309.         return(1);
  310.  
  311.     usRet = 2;
  312.     SemEnter();
  313.     if (QuerylatomName((LATOM)hsz1, sz, ENCODEBYTES * 2 + 1)) {
  314.         latom = Decode(&sz[ENCODEBYTES]);   /* use UPPERCASE form for comparison. */
  315.         if (QuerylatomName((LATOM)hsz2, sz, ENCODEBYTES * 2 + 1)) {
  316.             latom = latom - Decode(&sz[ENCODEBYTES]);
  317.             usRet = latom == 0 ? 0 : (latom > 0 ? 1 : -1);
  318.         }
  319.     }
  320.     SemLeave();
  321.     return(usRet);
  322. }
  323.  
  324.  
  325.     
  326.  
  327. /***************************** Private Function ****************************\
  328. * Returns the length of the latom given without NULL terminator.
  329. * Wild LATOMs have a length of 0.
  330. *
  331. * History:
  332. *   Created     9/12/89    Sanfords
  333. \***************************************************************************/
  334. USHORT QuerylatomLength(latom)
  335. LATOM latom;
  336. {
  337.     USHORT cb;
  338.     USHORT cbT = 0;
  339.     BYTE ab[ENCODEBYTES + 1];
  340.  
  341.     AssertF(HIUSHORT(latom) < cAtbls, "Invalid latom");
  342.     if (latom == 0)
  343.         return(0);
  344.     SemCheckIn();
  345.     while (TRUE) {
  346.         if (!(cb = WinQueryAtomLength(aAtbls[HIUSHORT(latom)],
  347.                 LOUSHORT(latom)))) {
  348.             AssertF(cbT == 0, "QuerylatomLength - failed on continued latom");
  349.             return(0);
  350.         }
  351.             
  352.         cbT += cb;
  353.         
  354.         if (cb <= MAX_LATOMSTRSIZE) {
  355.             return(cbT);
  356.         }
  357.             
  358.         /*
  359.          * it MUST be a huge latom.
  360.          */
  361.         if (!(WinQueryAtomName(aAtbls[HIUSHORT(latom)], LOUSHORT(latom),
  362.                 (PSZ)ab, ENCODEBYTES + 1))) {
  363.             AssertF(FALSE, "QuerylatomLength - Length but no name");
  364.             return(0);
  365.         }
  366.             
  367.         latom = Decode(ab);
  368.         cbT -= ENCODEBYTES;
  369.     }
  370. }
  371.  
  372.  
  373.  
  374. USHORT QuerylatomName(latom, psz, cchMax)
  375. LATOM latom;
  376. PSZ psz;
  377. USHORT cchMax;
  378. {
  379.     USHORT cb;
  380.     extern char szT[];
  381.  
  382.     if (HIUSHORT(latom) >= cAtbls) {
  383.         AssertF(FALSE, "Invalid latom");
  384.         psz[0] = '\0';
  385.         return(0);
  386.     }
  387.     
  388.     AssertF(latom != 0, "QuerylatomName - 0 latom");
  389.     SemCheckIn();
  390.     cb = WinQueryAtomLength(aAtbls[HIUSHORT(latom)], LOUSHORT(latom));
  391.     if (cb > MAX_LATOMSTRSIZE) {
  392.         if (!WinQueryAtomName(aAtbls[HIUSHORT(latom)], LOUSHORT(latom), szT,
  393.                 MAX_LATOMSTRSIZE + ENCODEBYTES + 1)) {
  394.             AssertF(FALSE, "QuerylatomName - length but no name");
  395.             return(0);
  396.         }
  397.         CopyBlock(szT + ENCODEBYTES, psz, min(MAX_LATOMSTRSIZE, cchMax));
  398.         latom = Decode((PBYTE)szT);
  399.         cb = MAX_LATOMSTRSIZE + QuerylatomName(latom, psz + MAX_LATOMSTRSIZE,
  400.                 cchMax > MAX_LATOMSTRSIZE ? cchMax - MAX_LATOMSTRSIZE : 0);
  401.         
  402.     } else {
  403.         WinQueryAtomName(aAtbls[HIUSHORT(latom)], LOUSHORT(latom), psz, cchMax);
  404.     }
  405.     psz[cchMax - 1] = '\0';     /* add NULL terminator */
  406.     return(min(cb, cchMax - 1));
  407. }
  408.  
  409.  
  410.  
  411. /***************************** Private Function ****************************\
  412. * This uses globals szT, aAtbls, cAtbls, and iAtblCurrent to add or
  413. * find the latom for psz depending on fAdd.
  414. *
  415. * History:
  416. *   Created     9/12/89    Sanfords
  417. \***************************************************************************/
  418. LATOM FindAddlatom(psz, fAdd)
  419. PSZ psz;
  420. BOOL fAdd;
  421. {
  422.     LATOM latom;
  423.  
  424.     AssertF(psz != NULL, "FindAddlatom - NULL psz");
  425.     AssertF(*psz != '\0', "FindAddlatom - NULL psz string");
  426.     SemCheckIn();
  427.     if (lstrlen(psz) > MAX_LATOMSTRSIZE) {
  428.         latom = FindAddlatom(psz + MAX_LATOMSTRSIZE, fAdd);
  429.         CopyBlock((PBYTE)psz, Encode((ULONG)latom, szT),
  430.                 (ULONG)MAX_LATOMSTRSIZE - ENCODEBYTES + 1);
  431.         szT[MAX_LATOMSTRSIZE + ENCODEBYTES] = '\0';
  432.         latom = FindAddlatomHelper(szT, fAdd);
  433.         return(latom);
  434.     } else {
  435.         return(FindAddlatomHelper(psz, fAdd));
  436.     }
  437. }
  438.  
  439.  
  440.  
  441.  
  442. LATOM FindAddlatomHelper(psz, fAdd)
  443. PSZ psz;
  444. BOOL fAdd;
  445. {
  446.     int i;
  447.     ATOM atom;
  448.     ATOM (APIENTRY *lpfn)(HATOMTBL, PSZ);
  449.     
  450.     SemCheckIn();
  451.     if (fAdd) {
  452.         AssertF(++cAtoms, "Possible atom count overflow");
  453.         lpfn = WinAddAtom;
  454.     } else 
  455.         lpfn = WinFindAtom;
  456.  
  457.     if (!(atom = (*lpfn)(aAtbls[i = iAtblCurrent], psz))) {
  458.         /*
  459.          * Must be full/not found, try all the existing tables
  460.          */
  461.         for (i = 0; i < cAtbls; i++) {
  462.             if (i != iAtblCurrent) {
  463.                 if (atom = (*lpfn)(aAtbls[i], psz)) {
  464.                     if (fAdd)
  465.                         iAtblCurrent = i;
  466.                     break;
  467.                 }
  468.             }
  469.         }
  470.          
  471.         if (!atom) {
  472.             if (fAdd) {
  473.                 /*
  474.                  * they're all full, make another table.
  475.                  */
  476.                 if (!AddAtomTable(FALSE)) {
  477.                     return(0L);
  478.                 }
  479.                 if (!(atom = (*lpfn)(aAtbls[iAtblCurrent], psz))) {
  480.                     return(0L); 
  481.                 }
  482.             } else {
  483.                 return(0L);
  484.             }
  485.         }
  486.     }
  487.     return((LATOM)MAKEP(i, atom));
  488. }
  489.  
  490.  
  491.     
  492.     
  493.  
  494. BOOL InclatomCount(latom)
  495. LATOM latom;
  496. {
  497.     AssertF(HIUSHORT(latom) < cAtbls, "Invalid latom");
  498.     AssertF(latom != 0, "InclatomCount - 0 latom");
  499.     SemCheckIn();
  500.     AssertF(++cAtoms, "Possible atom count overflow");
  501.     return(WinAddAtom(aAtbls[HIUSHORT(latom)], MAKEP(0XFFFF, LOUSHORT(latom))));
  502. }
  503.  
  504.  
  505.  
  506. BOOL Freelatom(latom)
  507. LATOM latom;
  508. {
  509.     AssertF(HIUSHORT(latom) < cAtbls, "Invalid latom");
  510.     AssertF(latom != 0, "Freelatom - 0 latom");
  511.     AssertF(WinQueryAtomUsage(aAtbls[HIUSHORT(latom)], LOUSHORT(latom)),
  512.             "Freelatom - Freeing Non-existing atom");
  513.     SemCheckIn();
  514.         
  515.     if (WinDeleteAtom(aAtbls[HIUSHORT(latom)], LOUSHORT(latom))) {
  516.         AssertF(FALSE, "Freelatom - WinDeleteAtom failed");
  517.         return(FALSE);
  518.     }
  519.     AssertF(--cAtoms >= 0, "Freelatom - negative atom count");
  520.     return(TRUE);
  521. }
  522.  
  523.  
  524.  
  525.  
  526. #ifdef DEBUG
  527. #define BASEVAL '0'     /* more readable for debugging */
  528. #else
  529. #define BASEVAL 1       /* less likely to conflict with a string */
  530. #endif
  531.  
  532. /***************************** Private Function ****************************\
  533. * Converts an latom into a ENCODEBYTES character string apropriate for
  534. * atomization. (NULL terminator must be added)
  535. *
  536. * History:
  537. *   Created     9/12/89    Sanfords
  538. \***************************************************************************/
  539. PBYTE Encode(latom, pb)
  540. ULONG latom;
  541. PBYTE pb;
  542. {
  543.     int i;
  544.  
  545.     
  546.     AssertF(HIUSHORT(latom) < cAtbls, "Invalid latom");
  547.     for (i = 0; i < ENCODEBYTES; i++) {
  548.         *pb++ = ((BYTE)latom & 0x0F) + BASEVAL;
  549.         latom >>= 4;
  550.     }
  551.     return(pb);
  552. }
  553.  
  554.  
  555.  
  556. /***************************** Private Function ****************************\
  557. * This takes a pointer to a buffer of 8 bytes which is a coded LATOM and
  558. * returns the LATOM.
  559. *
  560. * History:
  561. *   Created     9/12/89    Sanfords
  562. \***************************************************************************/
  563. LATOM Decode(pb)
  564. PBYTE pb;
  565. {
  566.     ULONG ul = 0;
  567.     int i;
  568.  
  569.     for (i = ENCODEBYTES - 1; i >= 0; i--) {
  570.         ul <<= 4;
  571.         ul += (ULONG)(pb[i] - BASEVAL);
  572.     }
  573.     return((LATOM)ul);
  574. }
  575.  
  576.  
  577. /*
  578.  * This routine extracts the hszItem out of an existing hData handle.
  579.  * local conversations can use the hsz directly out of the handle while
  580.  * non-dll conversations will have to generate the hsz from the string.
  581.  */
  582. HSZ GetHszItem(
  583. PMYDDES pmyddes,
  584. PCONVCONTEXT pCC,
  585. BOOL fAdd)
  586. {
  587.     if (CheckSel(SELECTOROF(pmyddes)) >= sizeof(MYDDES) &&
  588.             pmyddes->magic == MYDDESMAGIC) {
  589.         if (fAdd) 
  590.             IncHszCount(pmyddes->hszItem);
  591.         return(pmyddes->hszItem);
  592.     } else {
  593.         return(GetHsz(DDES_PSZITEMNAME(pmyddes), pCC->idCountry,
  594.                 pCC->usCodepage, fAdd));
  595.     }
  596. }
  597.