Files
reactos/reactos/lib/kernel32/misc/atom.c
Eric Kohl 648301897c Fixed header inclusion order.
svn path=/trunk/; revision=687
1999-10-07 23:46:27 +00:00

548 lines
10 KiB
C

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: lib/kernel32/misc/atom.c
* PURPOSE: Atom functions
* PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
* modified from WINE [ Onno Hovers, (onno@stack.urc.tue.nl) ]
* UPDATE HISTORY:
* Created 01/11/98
*/
#include <ddk/ntddk.h>
#include <kernel32/atom.h>
#include <kernel32/proc.h>
#include <kernel32/thread.h>
#include <wchar.h>
#include <string.h>
//#include <stdlib.h>
/*
* System global and local atom tables.
* What does "global" mean? The scope is
* the attached process or ANY process?
* In the second case, we need to call
* csrss.exe.
*/
#if 0
static ATOMTABLE GlobalAtomTable;
/* internal functions */
ATOM GLDeleteAtom(ATOMTABLE *at, ATOM nAtom);
ATOM AWGLAddAtom( ATOMTABLE *at, const WCHAR *lpString);
ATOM AWGLFindAtom(ATOMTABLE *at, const WCHAR *lpString);
UINT AWGLGetAtomName(ATOMTABLE *at,ATOM atom, WCHAR *lpString, int nSize);
static ATOMENTRY *GetAtomPointer(ATOMTABLE *,int);
static ATOMID AtomHashString(const WCHAR *,int *);
#define ATOMBASE 0xcc00
int unicode2ansi( char *ansi,const WCHAR *uni, int s);
int ansi2unicode( WCHAR *uni,const char *ansi, int s);
ATOM
STDCALL
GlobalDeleteAtom(
ATOM nAtom
)
{
return GLDeleteAtom(&GlobalAtomTable, nAtom);
}
BOOL
STDCALL
InitAtomTable(
DWORD nSize
)
{
// nSize should be a prime number
if ( nSize < 4 || nSize >= 512 )
{
nSize = 37;
}
if ( (GetCurrentPeb()->LocalAtomTable).lpDrvData == NULL )
{
(GetCurrentPeb()->LocalAtomTable).lpDrvData =
HeapAlloc(
GetProcessHeap(),
(HEAP_GENERATE_EXCEPTIONS | HEAP_ZERO_MEMORY),
(nSize * sizeof (ATOMENTRY))
);
}
return TRUE;
}
ATOM
STDCALL
DeleteAtom(
ATOM nAtom
)
{
return GLDeleteAtom(
& GetCurrentPeb()->LocalAtomTable,
nAtom
);
}
ATOM
STDCALL
GlobalAddAtomA(
LPCSTR lpString
)
{
UINT BufLen = strlen(lpString);
WCHAR * lpBuffer = (WCHAR *) HeapAlloc(
GetProcessHeap(),
(HEAP_GENERATE_EXCEPTIONS | HEAP_ZERO_MEMORY),
(BufLen * sizeof (WCHAR))
);
ATOM atom;
ansi2unicode(lpBuffer, lpString,BufLen);
atom = AWGLAddAtom(&GlobalAtomTable,lpBuffer );
HeapFree(GetProcessHeap(),0,lpBuffer);
return atom;
}
ATOM
STDCALL
GlobalAddAtomW(
LPCWSTR lpString
)
{
return AWGLAddAtom(&GlobalAtomTable, lpString);
}
ATOM
STDCALL
GlobalFindAtomA(
LPCSTR lpString
)
{
ATOM a;
UINT BufLen = strlen(lpString);
WCHAR *lpBuffer = (WCHAR *)HeapAlloc(GetProcessHeap(),HEAP_GENERATE_EXCEPTIONS|HEAP_ZERO_MEMORY,BufLen*sizeof(WCHAR));
ansi2unicode(lpBuffer, lpString,BufLen);
a = AWGLFindAtom(&GlobalAtomTable, lpBuffer);
HeapFree(GetProcessHeap(),0,lpBuffer);
return a;
}
ATOM
STDCALL
GlobalFindAtomW(
const WCHAR *lpString
)
{
return AWGLFindAtom(&GlobalAtomTable, lpString);
}
UINT
STDCALL
GlobalGetAtomNameA(
ATOM nAtom,
char *lpBuffer,
int nSize
)
{
WCHAR *lpUnicode = (WCHAR *)HeapAlloc(GetProcessHeap(),HEAP_GENERATE_EXCEPTIONS|HEAP_ZERO_MEMORY,nSize *sizeof(WCHAR));
UINT x = AWGLGetAtomName(&GlobalAtomTable,nAtom, lpUnicode,nSize);
unicode2ansi(lpBuffer,lpUnicode,nSize);
HeapFree(GetProcessHeap(),0,lpUnicode);
return x;
}
UINT
STDCALL
GlobalGetAtomNameW(
ATOM nAtom,
WCHAR * lpBuffer,
int nSize
)
{
return AWGLGetAtomName(&GlobalAtomTable, nAtom, lpBuffer, nSize);
}
ATOM
STDCALL
AddAtomA(
const char *lpString
)
{
UINT BufLen = strlen(lpString);
WCHAR *lpBuffer = (WCHAR*)HeapAlloc(GetProcessHeap(),HEAP_GENERATE_EXCEPTIONS|HEAP_ZERO_MEMORY,BufLen*2);
ATOM a;
ansi2unicode(lpBuffer, lpString,BufLen);
a = AWGLAddAtom(&GetCurrentPeb()->LocalAtomTable, lpBuffer);
HeapFree(GetProcessHeap(),0,lpBuffer);
return a;
}
ATOM
STDCALL
AddAtomW(
const WCHAR * lpString
)
{
return AWGLAddAtom(&GetCurrentPeb()->LocalAtomTable, lpString);
}
ATOM
STDCALL
FindAtomA(
const char *lpString
)
{
UINT BufLen = strlen(lpString);
WCHAR *lpBuffer = (WCHAR *)HeapAlloc(GetProcessHeap(),HEAP_GENERATE_EXCEPTIONS|HEAP_ZERO_MEMORY,BufLen*2);
ATOM a;
ansi2unicode(lpBuffer, lpString,BufLen);
a = AWGLFindAtom(&GetCurrentPeb()->LocalAtomTable, lpBuffer);
HeapFree(GetProcessHeap(),0,lpBuffer);
return a;
}
ATOM
STDCALL
FindAtomW(
const WCHAR * lpString
)
{
return AWGLFindAtom(&GetCurrentPeb()->LocalAtomTable, lpString);
}
UINT
STDCALL
GetAtomNameA(
ATOM nAtom,
char *lpBuffer,
int nSize
)
{
LPWSTR lpUnicode = (WCHAR *)HeapAlloc(GetProcessHeap(),HEAP_GENERATE_EXCEPTIONS|HEAP_ZERO_MEMORY,nSize *2);
UINT x = AWGLGetAtomName(&GlobalAtomTable, nAtom,lpUnicode,nSize);
unicode2ansi(lpBuffer,lpUnicode,nSize);
HeapFree(GetProcessHeap(),0,lpUnicode);
return x;
}
UINT
STDCALL
GetAtomNameW(
ATOM nAtom,
WCHAR * lpBuffer,
int nSize
)
{
return AWGLGetAtomName(&GetCurrentPeb()->LocalAtomTable,nAtom,lpBuffer, nSize);
}
ATOM
GLDeleteAtom(
ATOMTABLE *at, ATOM nAtom
)
{
ATOMENTRY *lp;
/* a free slot has q == 0 && refcnt == 0 */
if((lp = GetAtomPointer(at,nAtom - ATOMBASE))) {
if(lp->idsize)
lp->refcnt--;
if(lp->refcnt == 0) {
HeapFree(GetProcessHeap(),0,at->AtomTable);
at->AtomTable = NULL;
HeapFree(GetProcessHeap(),0,at->AtomData);
at->AtomData = NULL;
return lp->q = 0;
}
}
return nAtom;
}
ATOM
AWGLAddAtom(
ATOMTABLE *at, const WCHAR *lpString
)
{
ATOM atom;
ATOMID q;
LPATOMENTRY lp,lpfree;
int index,freeindex;
int atomlen;
int newlen;
/* if we already have it, bump refcnt */
if((atom = AWGLFindAtom(at, lpString ))) {
lp = GetAtomPointer(at,atom - ATOMBASE);
if(lp->idsize) lp->refcnt++;
return atom;
}
/* add to a free slot */
q = AtomHashString(lpString,&atomlen);
lpfree = 0;
freeindex = 0;
for(index = 0;(lp = GetAtomPointer(at,index));index++) {
if(lp->q == 0 && lp->refcnt == 0) {
if(lp->idsize > atomlen) {
if ((lpfree == 0) ||
(lpfree->idsize > lp->idsize)) {
lpfree = lp;
freeindex = index;
}
}
}
}
/* intatoms do not take space in data, but do get new entries */
/* an INTATOM will have length of 0 */
if(lpfree && atomlen) {
lpfree->q = q;
lpfree->refcnt = 1;
lstrcpynW(&at->AtomData[lpfree->idx],lpString,atomlen);
return freeindex + ATOMBASE;
}
/* no space was available, or we have an INTATOM */
/* so expand or create the table */
if(at->AtomTable == 0) {
at->AtomTable = (ATOMENTRY *) HeapAlloc(GetProcessHeap(),HEAP_GENERATE_EXCEPTIONS|HEAP_ZERO_MEMORY,sizeof(ATOMENTRY));
at->TableSize = 1;
lp = at->AtomTable;
index = 0;
} else {
at->TableSize++;
at->AtomTable = (ATOMENTRY *) HeapReAlloc(GetProcessHeap(),0,
(LPVOID) at->AtomTable,
at->TableSize * sizeof(ATOMENTRY));
lp = &at->AtomTable[at->TableSize - 1];
}
/* set in the entry */
lp->refcnt = 1;
lp->q = q;
lp->idsize = atomlen;
lp->idx = 0;
/* add an entry if not intatom... */
if(atomlen) {
newlen = at->DataSize + atomlen;
if(at->AtomData == 0) {
at->AtomData = (WCHAR *) HeapAlloc(GetProcessHeap(),HEAP_GENERATE_EXCEPTIONS|HEAP_ZERO_MEMORY,newlen*2);
lp->idx = 0;
} else {
at->AtomData = (WCHAR *) HeapReAlloc(GetProcessHeap(),0,at->AtomData,newlen*2);
lp->idx = at->DataSize;
}
lstrcpyW(&at->AtomData[lp->idx],lpString);
at->DataSize = newlen;
}
return index + ATOMBASE;
}
ATOM
AWGLFindAtom(
ATOMTABLE *at, const WCHAR *lpString
)
{
ATOMID q;
LPATOMENTRY lp;
int index;
int atomlen;
/* convert string to 'q', and get length */
q = AtomHashString(lpString,&atomlen);
/* find the q value, note: this could be INTATOM */
/* if q matches, then do case insensitive compare*/
for(index = 0;(lp = GetAtomPointer(at,index));index++) {
if(lp->q == q) {
if(HIWORD(lpString) == 0)
return ATOMBASE + index;
if(lstrcmpiW(&at->AtomData[lp->idx],lpString) == 0)
return ATOMBASE + index;
}
}
return 0;
}
UINT
AWGLGetAtomName(ATOMTABLE *at, ATOM atom, WCHAR *lpString,int len)
{
ATOMENTRY *lp;
WCHAR *atomstr;
int atomlen;
/* return the atom name, or create the INTATOM */
if((lp = GetAtomPointer(at,atom - ATOMBASE))) {
if(lp->idsize) {
atomlen = lstrlenW(atomstr = &at->AtomData[lp->idx]);
if (atomlen < len)
lstrcpyW(lpString,atomstr);
else {
lstrcpynW(lpString,atomstr,len-1);
lpString[len-1] = '\0';
}
return (UINT)lstrlenW(lpString);
} else {
//wsprintf((wchar *)lpString,"#%d",lp->q);
return (UINT)lstrlenW(lpString);
}
}
return 0;
}
/********************************************************/
/* convert alphanumeric string to a 'q' value. */
/* 'q' values do not need to be unique, they just limit */
/* the search we need to make to find a string */
/********************************************************/
static ATOMID
AtomHashString(const WCHAR * lp,int *lplen)
{
ATOMID q;
WCHAR *p,ch;
int len;
/* if we have an intatom... */
if(HIWORD(lp) == 0) {
if(lplen) *lplen = 0;
return (ATOMID)lp;
}
/* convert the string to an internal representation */
for(p=(WCHAR *)lp,q=0,len=0;(p++,ch=*p++);len++)
q = (q<<1) + iswlower(ch)?towupper(ch):ch;
/* 0 is reserved for empty slots */
if(q == 0)
q++;
/* avoid strlen later */
/* check out with unicode */
if(lplen) {
*lplen = ++len;
}
return q;
}
/********************************************************/
/* convert an atom index into a pointer into an */
/* atom table. This validates the pointer is in */
/* range, and that the data is accessible */
/********************************************************/
static ATOMENTRY *
GetAtomPointer(ATOMTABLE *at,int index)
{
ATOMENTRY *lp;
/* if no table, then no pointers */
if(at->AtomTable == 0)
return 0;
/* bad index */
if((index < 0) || (index >= at->TableSize))
return 0;
/* we have a pointer */
lp = &at->AtomTable[index];
/* is the index past stored data, validity check */
/* LATER: is the size of the entry within the available space */
if(lp->idx > at->DataSize)
return 0;
return lp;
}
int ansi2unicode( WCHAR *uni,const char *ansi, int s)
{
register int i;
for(i=0;i<=s;i++)
uni[i] = (WCHAR)ansi[i];
return i;
}
int
unicode2ansi( char *ansi,const WCHAR *uni, int s)
{
register int i;
for(i=0;i<=s;i++)
ansi[i] = (char)uni[i];
return i;
}
#endif
/* EOF */