This commit was manufactured by cvs2svn to create branch 'captive'.
[reactos.git] / lib / user32 / misc / strpool.c
diff --git a/lib/user32/misc/strpool.c b/lib/user32/misc/strpool.c
new file mode 100644 (file)
index 0000000..e33a1f4
--- /dev/null
@@ -0,0 +1,165 @@
+// strpool.c
+
+#include <windows.h>
+#include <ddk/ntddk.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;
+}