mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-09-02 04:13:34 +00:00
* lib/user32/include/.cvsignore: New file. * lib/user32/Makefile (TARGET_PCH): Set to include/user32.h. * lib/user32/*/*.c: Use pre-compiled header. * include/wine/debug.h (FIXME): Override previous declaration is needed. svn path=/trunk/; revision=10562
165 lines
3.7 KiB
C
165 lines
3.7 KiB
C
// strpool.c
|
|
|
|
#include "user32.h"
|
|
#include <strpool.h>
|
|
#include <string.h>
|
|
|
|
typedef struct tagHEAP_STRING_POOLA
|
|
{
|
|
char* data;
|
|
struct tagHEAP_STRING_POOLA* next;
|
|
} HEAP_STRING_POOLA, *PHEAP_STRING_POOLA;
|
|
|
|
typedef struct tagHEAP_STRING_POOLW
|
|
{
|
|
wchar_t* data;
|
|
struct tagHEAP_STRING_POOLW* next;
|
|
} HEAP_STRING_POOLW, *PHEAP_STRING_POOLW;
|
|
|
|
PHEAP_STRING_POOLA heap_string_Apool = NULL;
|
|
|
|
PHEAP_STRING_POOLW heap_string_Wpool = NULL;
|
|
|
|
HANDLE hProcessHeap = NULL;
|
|
|
|
PVOID
|
|
HEAP_alloc ( DWORD len )
|
|
{
|
|
return RtlAllocateHeap ( hProcessHeap, 0, len );
|
|
}
|
|
|
|
VOID
|
|
HEAP_free ( LPVOID memory )
|
|
{
|
|
RtlFreeHeap ( hProcessHeap, 0, memory );
|
|
}
|
|
|
|
LPWSTR
|
|
HEAP_strdupW ( LPCWSTR src, DWORD len )
|
|
{
|
|
LPWSTR dst;
|
|
|
|
if ( !src )
|
|
return NULL;
|
|
|
|
dst = HEAP_alloc ( (len+1) * sizeof(WCHAR) );
|
|
if ( !dst )
|
|
return NULL;
|
|
memcpy ( dst, src, (len+1)*sizeof(WCHAR) );
|
|
return dst;
|
|
}
|
|
|
|
NTSTATUS
|
|
HEAP_strcpyWtoA ( LPSTR lpszA, LPCWSTR lpszW, DWORD len )
|
|
{
|
|
NTSTATUS Status =
|
|
RtlUnicodeToMultiByteN ( lpszA, len, NULL, (LPWSTR)lpszW, len*sizeof(WCHAR) );
|
|
lpszA[len] = '\0';
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
HEAP_strcpyAtoW ( LPWSTR lpszW, LPCSTR lpszA, DWORD len )
|
|
{
|
|
NTSTATUS Status =
|
|
RtlMultiByteToUnicodeN ( lpszW, len*sizeof(WCHAR), NULL, (LPSTR)lpszA, len );
|
|
lpszW[len] = L'\0';
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
HEAP_strdupWtoA ( LPSTR* ppszA, LPCWSTR lpszW, DWORD len )
|
|
{
|
|
*ppszA = NULL;
|
|
|
|
if ( !lpszW )
|
|
return STATUS_SUCCESS;
|
|
|
|
*ppszA = HEAP_alloc ( len + 1 );
|
|
|
|
if ( !*ppszA )
|
|
return STATUS_NO_MEMORY;
|
|
|
|
return HEAP_strcpyWtoA ( *ppszA, lpszW, len );
|
|
}
|
|
|
|
NTSTATUS
|
|
HEAP_strdupAtoW ( LPWSTR* ppszW, LPCSTR lpszA, UINT* NewLen )
|
|
{
|
|
ULONG len;
|
|
|
|
*ppszW = NULL;
|
|
|
|
if ( !lpszA )
|
|
return STATUS_SUCCESS;
|
|
|
|
len = lstrlenA ( lpszA );
|
|
|
|
*ppszW = HEAP_alloc ( (len+1) * sizeof(WCHAR) );
|
|
|
|
if ( !*ppszW )
|
|
return STATUS_NO_MEMORY;
|
|
|
|
if ( NewLen ) *NewLen = (UINT)len;
|
|
|
|
return HEAP_strcpyAtoW ( *ppszW, lpszA, len );
|
|
}
|
|
|
|
char* heap_string_poolA ( const wchar_t* pstrW, DWORD length )
|
|
{
|
|
PHEAP_STRING_POOLA pPoolEntry = heap_string_Apool;
|
|
char* pstrA = NULL;
|
|
HEAP_strdupWtoA ( &pstrA, pstrW, length );
|
|
if ( !pstrA )
|
|
return NULL;
|
|
while ( pPoolEntry )
|
|
{
|
|
if ( !strcmp ( pPoolEntry->data, pstrA ) )
|
|
{
|
|
HEAP_free ( pstrA );
|
|
return pPoolEntry->data;
|
|
}
|
|
pPoolEntry = pPoolEntry->next;
|
|
}
|
|
pPoolEntry = (PHEAP_STRING_POOLA)HEAP_alloc ( sizeof(HEAP_STRING_POOLA) );
|
|
pPoolEntry->data = pstrA;
|
|
|
|
// IMHO, synchronization is *not* needed here. This data is process-
|
|
// local, so the only possible contention is among threads. If a
|
|
// conflict does occur, the only problem will be a small memory
|
|
// leak that gets cleared up when the heap is destroyed by the
|
|
// process exiting.
|
|
pPoolEntry->next = heap_string_Apool;
|
|
heap_string_Apool = pPoolEntry;
|
|
return pPoolEntry->data;
|
|
}
|
|
|
|
wchar_t* heap_string_poolW ( const wchar_t* pstrWSrc, DWORD length )
|
|
{
|
|
PHEAP_STRING_POOLW pPoolEntry = heap_string_Wpool;
|
|
wchar_t* pstrW = NULL;
|
|
pstrW = HEAP_strdupW ( (LPWSTR)pstrWSrc, length );
|
|
if ( !pstrW )
|
|
return NULL;
|
|
while ( pPoolEntry )
|
|
{
|
|
if ( !wcscmp (pPoolEntry->data, pstrW ) )
|
|
{
|
|
HEAP_free ( pstrW );
|
|
return pPoolEntry->data;
|
|
}
|
|
pPoolEntry = pPoolEntry->next;
|
|
}
|
|
pPoolEntry = (PHEAP_STRING_POOLW)HEAP_alloc ( sizeof(HEAP_STRING_POOLW) );
|
|
pPoolEntry->data = pstrW;
|
|
|
|
// IMHO, synchronization is *not* needed here. This data is process-
|
|
// local, so the only possible contention is among threads. If a
|
|
// conflict does occur, the only problem will be a small memory
|
|
// leak that gets cleared up when the heap is destroyed by the
|
|
// process exiting.
|
|
pPoolEntry->next = heap_string_Wpool;
|
|
heap_string_Wpool = pPoolEntry;
|
|
return pPoolEntry->data;
|
|
}
|