e33a1f45468a654d78583c19f43d39f8b9a814cf
[reactos.git] / lib / user32 / misc / strpool.c
1 // strpool.c
2
3 #include <windows.h>
4 #include <ddk/ntddk.h>
5 #include <strpool.h>
6 #include <string.h>
7
8 typedef struct tagHEAP_STRING_POOLA
9 {
10         char* data;
11         struct tagHEAP_STRING_POOLA* next;
12 } HEAP_STRING_POOLA, *PHEAP_STRING_POOLA;
13
14 typedef struct tagHEAP_STRING_POOLW
15 {
16         wchar_t* data;
17         struct tagHEAP_STRING_POOLW* next;
18 } HEAP_STRING_POOLW, *PHEAP_STRING_POOLW;
19
20 PHEAP_STRING_POOLA heap_string_Apool = NULL;
21
22 PHEAP_STRING_POOLW heap_string_Wpool = NULL;
23
24 HANDLE hProcessHeap = NULL;
25
26 PVOID
27 HEAP_alloc ( DWORD len )
28 {
29   return RtlAllocateHeap ( hProcessHeap, 0, len );
30 }
31
32 VOID
33 HEAP_free ( LPVOID memory )
34 {
35   RtlFreeHeap ( hProcessHeap, 0, memory );
36 }
37
38 LPWSTR
39 HEAP_strdupW ( LPCWSTR src, DWORD len )
40 {
41   LPWSTR dst;
42
43   if ( !src )
44     return NULL;
45
46   dst = HEAP_alloc ( (len+1) * sizeof(WCHAR) );
47   if ( !dst )
48     return NULL;
49   memcpy ( dst, src, (len+1)*sizeof(WCHAR) );
50   return dst;
51 }
52
53 NTSTATUS
54 HEAP_strcpyWtoA ( LPSTR lpszA, LPCWSTR lpszW, DWORD len )
55 {
56   NTSTATUS Status =
57     RtlUnicodeToMultiByteN ( lpszA, len, NULL, (LPWSTR)lpszW, len*sizeof(WCHAR) );
58   lpszA[len] = '\0';
59   return Status;
60 }
61
62 NTSTATUS
63 HEAP_strcpyAtoW ( LPWSTR lpszW, LPCSTR lpszA, DWORD len )
64 {
65   NTSTATUS Status =
66     RtlMultiByteToUnicodeN ( lpszW, len*sizeof(WCHAR), NULL, (LPSTR)lpszA, len ); 
67   lpszW[len] = L'\0';
68   return Status;
69 }
70
71 NTSTATUS
72 HEAP_strdupWtoA ( LPSTR* ppszA, LPCWSTR lpszW, DWORD len )
73 {
74   *ppszA = NULL;
75
76   if ( !lpszW )
77     return STATUS_SUCCESS;
78
79   *ppszA = HEAP_alloc ( len + 1 );
80
81   if ( !*ppszA )
82     return STATUS_NO_MEMORY;
83
84   return HEAP_strcpyWtoA ( *ppszA, lpszW, len );
85 }
86
87 NTSTATUS
88 HEAP_strdupAtoW ( LPWSTR* ppszW, LPCSTR lpszA, UINT* NewLen )
89 {
90   ULONG len;
91
92   *ppszW = NULL;
93
94   if ( !lpszA )
95     return STATUS_SUCCESS;
96
97   len = lstrlenA ( lpszA );
98
99   *ppszW = HEAP_alloc ( (len+1) * sizeof(WCHAR) );
100
101   if ( !*ppszW )
102     return STATUS_NO_MEMORY;
103
104   if ( NewLen ) *NewLen = (UINT)len;
105
106   return HEAP_strcpyAtoW ( *ppszW, lpszA, len );
107 }
108
109 char* heap_string_poolA ( const wchar_t* pstrW, DWORD length )
110 {
111   PHEAP_STRING_POOLA pPoolEntry = heap_string_Apool;
112   char* pstrA = NULL;
113   HEAP_strdupWtoA ( &pstrA, pstrW, length );
114   if ( !pstrA )
115     return NULL;
116   while ( pPoolEntry )
117   {
118     if ( !strcmp ( pPoolEntry->data, pstrA ) )
119     {
120       HEAP_free ( pstrA );
121       return pPoolEntry->data;
122     }
123     pPoolEntry = pPoolEntry->next;
124   }
125   pPoolEntry = (PHEAP_STRING_POOLA)HEAP_alloc ( sizeof(HEAP_STRING_POOLA) );
126   pPoolEntry->data = pstrA;
127
128   // IMHO, synchronization is *not* needed here. This data is process-
129   // local, so the only possible contention is among threads. If a
130   // conflict does occur, the only problem will be a small memory
131   // leak that gets cleared up when the heap is destroyed by the
132   // process exiting.
133   pPoolEntry->next = heap_string_Apool;
134   heap_string_Apool = pPoolEntry;
135   return pPoolEntry->data;
136 }
137
138 wchar_t* heap_string_poolW ( const wchar_t* pstrWSrc, DWORD length )
139 {
140   PHEAP_STRING_POOLW pPoolEntry = heap_string_Wpool;
141   wchar_t* pstrW = NULL;
142   pstrW = HEAP_strdupW ( (LPWSTR)pstrWSrc, length );
143   if ( !pstrW )
144     return NULL;
145   while ( pPoolEntry )
146   {
147     if ( !wcscmp (pPoolEntry->data, pstrW ) )
148     {
149       HEAP_free ( pstrW );
150       return pPoolEntry->data;
151     }
152     pPoolEntry = pPoolEntry->next;
153   }
154   pPoolEntry = (PHEAP_STRING_POOLW)HEAP_alloc ( sizeof(HEAP_STRING_POOLW) );
155   pPoolEntry->data = pstrW;
156
157   // IMHO, synchronization is *not* needed here. This data is process-
158   // local, so the only possible contention is among threads. If a
159   // conflict does occur, the only problem will be a small memory
160   // leak that gets cleared up when the heap is destroyed by the
161   // process exiting.
162   pPoolEntry->next = heap_string_Wpool;
163   heap_string_Wpool = pPoolEntry;
164   return pPoolEntry->data;
165 }