ReactOS  0.4.15-dev-1632-g4e289ce
stringutil.cpp
Go to the documentation of this file.
1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7  StringUtil.cpp
8 
9 Abstract:
10 
11  This module implements string utlities in the framework
12 
13 Author:
14 
15 
16 
17 Environment:
18 
19  Both kernel and user mode
20 
21 Revision History:
22 
23 --*/
24 
25 #include "fxsupportpch.hpp"
26 
27 extern "C" {
28 // #include "StringUtil.tmh"
29 }
30 
31 size_t
33  __in FxCollectionInternal *StringCollection,
35  __out_opt PBOOLEAN ContainsOnlyStrings
36  )
37 {
38  size_t cbLength;
41 
42  cbLength = 0;
43 
44  end = StringCollection->End();
45  for (cur = StringCollection->Start();
46  cur != end;
47  cur = cur->Next()) {
49 
51  *ContainsOnlyStrings = FALSE;
52  return 0;
53  }
54 
55  cbLength += pString->ByteLength(TRUE);
56  }
57 
58  if (ContainsOnlyStrings != NULL) {
59  *ContainsOnlyStrings = TRUE;
60  }
61 
62  if (StringCollection->Count() == 0) {
63  //
64  // If there are not entries, we still need 2 NULLs
65  //
66  cbLength = sizeof(UNICODE_NULL) * 2;
67  }
68  else {
69  //
70  // Extra NULL
71  //
72  cbLength += sizeof(UNICODE_NULL);
73  }
74 
75  //
76  // ASSERT that we are reporting an integral number of WCHARs in bytes
77  //
78  ASSERT((cbLength % sizeof(WCHAR)) == 0);
79 
80  return cbLength;
81 }
82 
83 size_t
86  )
87 {
88  PCWSTR pCur;
89  size_t cbSize, cbLength;
90 
91  cbSize = 0;
92 
93  pCur = MultiSz;
94 
95  while (*pCur != NULL) {
96  //
97  // Compute length of string including terminating NULL
98  //
99  cbLength = (wcslen(pCur) + 1) * sizeof(WCHAR);
100 
101  cbSize += cbLength;
102  pCur = (PWSTR) WDF_PTR_ADD_OFFSET(pCur, cbLength);
103  }
104 
105  if (cbSize == 0) {
106  //
107  // If there are no strings, we still need 2 NULLs
108  //
109  cbSize = sizeof(UNICODE_NULL);
110  }
111 
112  //
113  // Final NULL which makes this a multi sz
114  //
115  cbSize += sizeof(UNICODE_NULL);
116 
117  //
118  // ASSERT that we are reporting an integral number of WCHARs in bytes
119  //
120  ASSERT((cbSize % sizeof(WCHAR)) == 0);
121 
122  return cbSize;
123 }
124 
125 #pragma prefast(push)
126 // Caller is responsible for allocating the correct amount of memory.
127 #pragma prefast(disable:__WARNING_INCORRECT_ANNOTATION_STRING )
128 PWSTR
131  __in FxCollectionInternal* StringCollection
132  )
133 {
134  LPWSTR pCur;
135  ULONG length;
137 
138  pCur = Buffer;
139  end = StringCollection->End();
140 
141  for (cur = StringCollection->Start(); cur != end; cur = cur->Next()) {
142  FxString* pSourceString;
143 
144  pSourceString = (FxString *) cur->m_Object;
145 
146  length = pSourceString->ByteLength(TRUE);
147  RtlCopyMemory(pCur, pSourceString->Buffer(), length);
148 
149  //
150  // Length is expressed in number of bytes, not number of
151  // characters.
152  //
153  // length includes the NULL.
154  //
156  }
157 
158  //
159  // If there are no entries, we still need 2 NULLs.
160  //
161  if (StringCollection->Count() == 0) {
162  *pCur = UNICODE_NULL;
163  pCur++;
164  }
165 
166  //
167  // double NULL terminate the string
168  //
169  *pCur = UNICODE_NULL;
170 
171  //
172  // Return the start of the next location in the buffer
173  //
174  return pCur + 1;
175 }
176 #pragma prefast(pop)
177 
179 NTSTATUS
181  __in PFX_DRIVER_GLOBALS FxDriverGlobals,
182  __in const UNICODE_STRING* Source,
184  )
185 /*++
186 
187 Routine Description:
188  Makes a deep copy from Source to Destination.
189 
190  Destination is assumed to have been initialized by the caller, be owned by
191  an internal Fx object. Destination could already contain a previously
192  allocated buffer. If one exists and is large enough, it will be reused
193  for the copy.
194 
195  This function guarantees that the Buffer will be NULL terminated. While
196  this is not necessary because Length describes the length of the buffer, the
197  resulting buffer can be copied back to the client driver and we cannot trust
198  the client driver to treat the string as an unterminated buffer, typically
199  the client driver will just extract the buffer and treat it as NULL
200  terminated. To be defensive with this type of (mis)use, we always NULL
201  terminate the resuling Buffer.
202 
203 Arguments:
204  Source - source struct to copy from. This string can originate from the
205  client driver.
206 
207  Destination - destination struct to copy to. This struct is assumed to be
208  internal and is not given to the outside caller
209 
210 Return Value:
211  NTSTATUS
212 
213  --*/
214 {
216  USHORT srcCbLength, srcCbLengthAndNull, dstMaxCbLength;
217 
218  //
219  // NOTE: We assume the sources string will be smaller than 64k.
220  //
221  srcCbLength = Source->Length;
222  dstMaxCbLength = Destination->MaximumLength;
223 
224  status = RtlUShortAdd(srcCbLength,
225  sizeof(UNICODE_NULL),
226  &srcCbLengthAndNull);
227  if (!NT_SUCCESS(status)) {
229  FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
230  "Interger overflow occured when duplicating string %!STATUS!",
231  status);
232  return status;
233  }
234 
235  //
236  // First see if we already have enough memory to hold the string + a NULL
237  //
238  if (dstMaxCbLength < srcCbLengthAndNull) {
239  //
240  // Allocate enough memory for the source string and a NULL character
241  //
242  dstMaxCbLength = srcCbLengthAndNull;
243 
244  //
245  // We need to allocate memory. Free any old memory first.
246  //
247  if (Destination->Buffer != NULL) {
249 
251  }
252 
253  Destination->Buffer = (PWSTR) FxPoolAllocate(
254  FxDriverGlobals, PagedPool, dstMaxCbLength);
255 
256  if (Destination->Buffer == NULL) {
259  FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
260  "Failed to allocate memory when duplicating string %!STATUS!",
261  status);
262  return status;
263  }
264 
265  Destination->MaximumLength = dstMaxCbLength;
266  }
267 
268  //
269  // If we get here and we have a buffer, then we can just copy the
270  // string into the buffer.
271  //
272  RtlCopyMemory(Destination->Buffer, Source->Buffer, srcCbLength);
273  Destination->Length = srcCbLength;
274 
275  //
276  // Make sure the string is NULL terminated and there is room for the NULL
277  //
278  ASSERT(Destination->Length + sizeof(UNICODE_NULL) <=
281 
282  return STATUS_SUCCESS;
283 }
284 
286 PWCHAR
288  __in PFX_DRIVER_GLOBALS FxDriverGlobals,
289  __in const UNICODE_STRING* Source
290  )
291 {
292  PWSTR pDuplicate;
293 
294  pDuplicate = (PWSTR) FxPoolAllocate(
295  FxDriverGlobals, PagedPool, Source->Length + sizeof(UNICODE_NULL));
296 
297  if (pDuplicate != NULL) {
298  RtlCopyMemory(pDuplicate, Source->Buffer, Source->Length);
299 
300  //
301  // Make sure the string is NULL terminated. We can safely do this
302  // because we allocated an extra WCHAR for the null terminator.
303  //
304  pDuplicate[Source->Length/sizeof(WCHAR)] = UNICODE_NULL;
305  }
306 
307  return pDuplicate;
308 }
const uint16_t * PCWSTR
Definition: typedefs.h:57
#define _Must_inspect_result_
Definition: no_sal2.h:62
Definition: msg.c:1065
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
size_t FxCalculateTotalStringSize(__in FxCollectionInternal *StringCollection, __in BOOLEAN Verify, __out_opt PBOOLEAN ContainsOnlyStrings)
Definition: stringutil.cpp:32
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define WDF_PTR_ADD_OFFSET(_ptr, _offset)
Definition: wdfcore.h:144
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
#define TRUE
Definition: types.h:120
PWSTR FxCopyMultiSz(__out LPWSTR Buffer, __in FxCollectionInternal *StringCollection)
Definition: stringutil.cpp:129
uint16_t * PWSTR
Definition: typedefs.h:56
LONG NTSTATUS
Definition: precomp.h:26
uint16_t * PWCHAR
Definition: typedefs.h:56
_Must_inspect_result_ NTSTATUS FxDuplicateUnicodeString(__in PFX_DRIVER_GLOBALS FxDriverGlobals, __in const UNICODE_STRING *Source, __out PUNICODE_STRING Destination)
Definition: stringutil.cpp:180
WDFTYPE GetType(VOID)
Definition: fxobject.hpp:742
size_t FxCalculateTotalMultiSzStringSize(__in __nullnullterminated PCWSTR MultiSz)
Definition: stringutil.cpp:84
#define __out_opt
Definition: dbghelp.h:65
#define FALSE
Definition: types.h:117
#define UNICODE_NULL
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
#define __out
Definition: dbghelp.h:62
unsigned char BOOLEAN
Definition: bufpool.h:45
#define ASSERT(a)
Definition: mode.c:45
if(!(yy_init))
Definition: macro.lex.yy.c:714
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
FxObject * m_Object
_In_ PUNICODE_STRING _Inout_ PUNICODE_STRING Destination
Definition: rtlfuncs.h:2937
__inline PWCHAR Buffer(VOID)
Definition: fxstring.hpp:144
GLuint GLuint end
Definition: gl.h:1545
char * PBOOLEAN
Definition: retypes.h:11
FxCollectionEntry * cur
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
FxString * pString
__inline USHORT ByteLength(__in BOOLEAN IncludeNull)
Definition: fxstring.hpp:94
unsigned short USHORT
Definition: pedump.c:61
SINGLE_LIST_ENTRY * pCur
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP, "Enter, WDFDEVICE %p", Device)
#define NULL
Definition: types.h:112
#define __nullnullterminated
Definition: sal.h:2871
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
_In_ UINT _In_ UINT _In_ PNDIS_PACKET Source
Definition: ndis.h:3167
#define STATUS_SUCCESS
Definition: shellext.h:65
_Must_inspect_result_ PWCHAR FxDuplicateUnicodeStringToString(__in PFX_DRIVER_GLOBALS FxDriverGlobals, __in const UNICODE_STRING *Source)
Definition: stringutil.cpp:287
WCHAR * LPWSTR
Definition: xmlstorage.h:184
void FxPoolFree(__in_xcount(ptr is at an offset from AllocationStart) PVOID ptr)
Definition: wdfpool.cpp:361
#define TRACINGERROR
Definition: dbgtrace.h:63
#define __in
Definition: dbghelp.h:35
static SERVICE_STATUS status
Definition: service.c:31
FxCollectionEntry * Next(VOID)
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define WDF_PTR_ADD_OFFSET_TYPE(_ptr, _offset, _type)
Definition: wdfcore.h:141
Definition: ps.c:97