Sync up to trunk head.
[reactos.git] / lib / dnslib / string.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS DNS Shared Library
4 * FILE: lib/dnslib/string.c
5 * PURPOSE: functions for string manipulation and conversion.
6 */
7
8 /* INCLUDES ******************************************************************/
9 #include "precomp.h"
10
11 /* DATA **********************************************************************/
12
13 /* FUNCTIONS *****************************************************************/
14
15 ULONG
16 WINAPI
17 Dns_StringCopy(OUT PVOID Destination,
18 IN OUT PULONG DestinationSize,
19 IN PVOID String,
20 IN ULONG StringSize OPTIONAL,
21 IN DWORD InputType,
22 IN DWORD OutputType)
23 {
24 ULONG DestSize;
25 ULONG OutputSize = 0;
26
27 /* Check if the caller already gave us the string size */
28 if (!StringSize)
29 {
30 /* He didn't, get the input type */
31 if (InputType == UnicodeString)
32 {
33 /* Unicode string, calculate the size */
34 StringSize = (ULONG)wcslen((LPWSTR)String);
35 }
36 else
37 {
38 /* ANSI or UTF-8 sting, get the size */
39 StringSize = (ULONG)strlen((LPSTR)String);
40 }
41 }
42
43 /* Check if we have a limit on the desination size */
44 if (DestinationSize)
45 {
46 /* Make sure that we can respect it */
47 DestSize = Dns_GetBufferLengthForStringCopy(String,
48 StringSize,
49 InputType,
50 OutputType);
51 if (*DestinationSize < DestSize)
52 {
53 /* Fail due to missing buffer space */
54 SetLastError(ERROR_MORE_DATA);
55
56 /* Return how much data we actually need */
57 *DestinationSize = DestSize;
58 return 0;
59 }
60 else if (!DestSize)
61 {
62 /* Fail due to invalid data */
63 SetLastError(ERROR_INVALID_DATA);
64 return 0;
65 }
66
67 /* Return how much data we actually need */
68 *DestinationSize = DestSize;
69 }
70
71 /* Now check if this is a Unicode String as input */
72 if (InputType == UnicodeString)
73 {
74 /* Check if the output is ANSI */
75 if (OutputType == AnsiString)
76 {
77 /* Convert and return the final desination size */
78 OutputSize = WideCharToMultiByte(CP_ACP,
79 0,
80 String,
81 StringSize,
82 Destination,
83 -1,
84 NULL,
85 NULL) + 1;
86 }
87 else if (OutputType == UnicodeString)
88 {
89 /* Copy the string */
90 StringSize = StringSize * sizeof(WCHAR);
91 RtlMoveMemory(Destination, String, StringSize);
92
93 /* Return output length */
94 OutputSize = StringSize + 2;
95 }
96 else if (OutputType == Utf8String)
97 {
98 /* FIXME */
99 OutputSize = 0;
100 }
101 }
102 else if (InputType == AnsiString)
103 {
104 /* It's ANSI, is the output ansi too? */
105 if (OutputType == AnsiString)
106 {
107 /* Copy the string */
108 RtlMoveMemory(Destination, String, StringSize);
109
110 /* Return output length */
111 OutputSize = StringSize + 1;
112 }
113 else if (OutputType == UnicodeString)
114 {
115 /* Convert to Unicode and return size */
116 OutputSize = MultiByteToWideChar(CP_ACP,
117 0,
118 String,
119 StringSize,
120 Destination,
121 -1) * sizeof(WCHAR) + 2;
122 }
123 else if (OutputType == Utf8String)
124 {
125 /* FIXME */
126 OutputSize = 0;
127 }
128 }
129 else if (InputType == Utf8String)
130 {
131 /* FIXME */
132 OutputSize = 0;
133 }
134
135 /* Return the output size */
136 return OutputSize;
137 }
138
139 LPWSTR
140 WINAPI
141 Dns_CreateStringCopy_W(IN LPWSTR Name)
142 {
143 SIZE_T StringLength;
144 LPWSTR NameCopy;
145
146 /* Make sure that we have a name */
147 if (!Name)
148 {
149 /* Fail */
150 SetLastError(ERROR_INVALID_PARAMETER);
151 return NULL;
152 }
153
154 /* Find out the size of the string */
155 StringLength = (wcslen(Name) + 1) * sizeof(WCHAR);
156
157 /* Allocate space for the copy */
158 NameCopy = Dns_AllocZero(StringLength);
159 if (NameCopy)
160 {
161 /* Copy it */
162 RtlCopyMemory(NameCopy, Name, StringLength);
163 }
164 else
165 {
166 /* Fail */
167 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
168 }
169
170 /* Return the copy */
171 return NameCopy;
172 }
173
174 ULONG
175 WINAPI
176 Dns_GetBufferLengthForStringCopy(IN PVOID String,
177 IN ULONG Size OPTIONAL,
178 IN DWORD InputType,
179 IN DWORD OutputType)
180 {
181 ULONG OutputSize = 0;
182
183 /* Check what kind of string this is */
184 if (InputType == UnicodeString)
185 {
186 /* Check if we have a size */
187 if (!Size)
188 {
189 /* Get it ourselves */
190 Size = (ULONG)wcslen(String);
191 }
192
193 /* Check the output type */
194 if (OutputType == UnicodeString)
195 {
196 /* Convert the size to bytes */
197 OutputSize = (Size + 1) * sizeof(WCHAR);
198 }
199 else if (OutputType == Utf8String)
200 {
201 /* FIXME */
202 OutputSize = 0;
203 }
204 else
205 {
206 /* Find out how much it will be in ANSI bytes */
207 OutputSize = WideCharToMultiByte(CP_ACP,
208 0,
209 String,
210 Size,
211 NULL,
212 0,
213 NULL,
214 NULL) + 1;
215 }
216 }
217 else if (InputType == AnsiString)
218 {
219 /* Check if we have a size */
220 if (!Size)
221 {
222 /* Get it ourselves */
223 Size = (ULONG)strlen(String);
224 }
225
226 /* Check the output type */
227 if (OutputType == AnsiString)
228 {
229 /* Just add a byte for the null char */
230 OutputSize = Size + 1;
231 }
232 else if (OutputType == UnicodeString)
233 {
234 /* Calculate the bytes for a Unicode string */
235 OutputSize = (MultiByteToWideChar(CP_ACP,
236 0,
237 String,
238 Size,
239 NULL,
240 0) + 1) * sizeof(WCHAR);
241 }
242 else if (OutputType == Utf8String)
243 {
244 /* FIXME */
245 OutputSize = 0;
246 }
247 }
248 else if (InputType == Utf8String)
249 {
250 /* FIXME */
251 OutputSize = 0;
252 }
253
254 /* Return the size required */
255 return OutputSize;
256 }
257