xref: /reactos/sdk/lib/dnslib/string.c (revision 845faec4)
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 
258