1
2 #include "precomp.h"
3
4 #include <winuser.h>
5 #include <winnls.h>
6 #include <wchar.h>
7 #include <sal.h>
8
9 #include "mswhelper.h"
10
11 #define MSW_BUFSIZE 512
12 #define MAX_ARRAY_SIZE 5
13
14 void
mswBufferInit(_Inout_ PMSW_BUFFER mswBuf,_In_ BYTE * buffer,_In_ DWORD bufferSize)15 mswBufferInit(_Inout_ PMSW_BUFFER mswBuf,
16 _In_ BYTE* buffer,
17 _In_ DWORD bufferSize)
18 {
19 RtlZeroMemory(mswBuf, sizeof(*mswBuf));
20 RtlZeroMemory(buffer, bufferSize);
21 mswBuf->bytesMax = bufferSize;
22 mswBuf->buffer = buffer;
23 mswBuf->bufendptr = buffer;
24 mswBuf->bufok = TRUE;
25 }
26
27 BOOL
mswBufferCheck(_Inout_ PMSW_BUFFER mswBuf,_In_ DWORD count)28 mswBufferCheck(_Inout_ PMSW_BUFFER mswBuf,
29 _In_ DWORD count)
30 {
31 if (mswBuf->bytesUsed + count <= mswBuf->bytesMax)
32 return TRUE;
33
34 mswBuf->bufok = FALSE;
35 return FALSE;
36 }
37
38 BOOL
mswBufferIncUsed(_Inout_ PMSW_BUFFER mswBuf,_In_ DWORD count)39 mswBufferIncUsed(_Inout_ PMSW_BUFFER mswBuf,
40 _In_ DWORD count)
41 {
42 if (!mswBufferCheck(mswBuf, count))
43 return FALSE;
44
45 mswBuf->bytesUsed += count;
46 mswBuf->bufendptr += count;
47 return TRUE;
48 }
49
50 BYTE*
mswBufferEndPtr(_Inout_ PMSW_BUFFER mswBuf)51 mswBufferEndPtr(_Inout_ PMSW_BUFFER mswBuf)
52 {
53 return mswBuf->bufendptr;
54 }
55
56 BOOL
mswBufferAppend(_Inout_ PMSW_BUFFER mswBuf,_In_ void * dataToAppend,_In_ DWORD dataSize)57 mswBufferAppend(_Inout_ PMSW_BUFFER mswBuf,
58 _In_ void *dataToAppend,
59 _In_ DWORD dataSize)
60 {
61 if (!mswBufferCheck(mswBuf, dataSize))
62 return FALSE;
63
64 RtlCopyMemory(mswBuf->bufendptr, dataToAppend, dataSize);
65 mswBuf->bytesUsed += dataSize;
66 mswBuf->bufendptr += dataSize;
67
68 return TRUE;
69 }
70
mswBufferAppendStrA(_Inout_ PMSW_BUFFER mswBuf,_In_ char * str)71 BOOL mswBufferAppendStrA(_Inout_ PMSW_BUFFER mswBuf,
72 _In_ char* str)
73 {
74 return mswBufferAppend(mswBuf, str, strlen(str) + sizeof(char));
75 }
76
77 BOOL
mswBufferAppendStrW(_Inout_ PMSW_BUFFER mswBuf,_In_ WCHAR * str)78 mswBufferAppendStrW(_Inout_ PMSW_BUFFER mswBuf,
79 _In_ WCHAR* str)
80 {
81 int bytelen = (wcslen(str) + 1) * sizeof(WCHAR);
82 return mswBufferAppend(mswBuf, str, bytelen);
83 }
84
85 BOOL
mswBufferAppendPtr(_Inout_ PMSW_BUFFER mswBuf,_In_ void * ptr)86 mswBufferAppendPtr(_Inout_ PMSW_BUFFER mswBuf,
87 _In_ void* ptr)
88 {
89 return mswBufferAppend(mswBuf, &ptr, sizeof(ptr));
90 }
91
92 /* lst = pointer to pointer of items
93
94 *lst[0] = 1st item
95 *lst[1] = 2nd item
96 ...
97 lst[n] = NULL = End of List
98
99 itemLength = data in Bytes for each item.
100
101 ptrofs = delta relative to mswBuf.buffer
102 */
103 BOOL
mswBufferAppendLst(_Inout_ PMSW_BUFFER mswBuf,_In_ void ** lst,_In_ DWORD itemByteLength,_In_opt_ int ptrofs)104 mswBufferAppendLst(_Inout_ PMSW_BUFFER mswBuf,
105 _In_ void **lst,
106 _In_ DWORD itemByteLength,
107 _In_opt_ int ptrofs)
108 {
109 DWORD lstItemCount;
110 DWORD lstByteSize;
111 DWORD_PTR lstDataPos;
112 DWORD i1;
113 UINT_PTR *ptrSrcLstPos;
114
115 /* calculate size of list */
116 ptrSrcLstPos = (UINT_PTR*)lst;
117 lstItemCount = 0;
118 while (*ptrSrcLstPos != (UINT_PTR)NULL)
119 {
120 lstItemCount++;
121 ptrSrcLstPos++;
122 }
123
124 lstByteSize = ((lstItemCount + 1) * sizeof(UINT_PTR)) + /* item-pointer + null-ptr (for end) */
125 (lstItemCount * itemByteLength); /* item-data */
126
127 if (mswBuf->bytesUsed + lstByteSize > mswBuf->bytesMax)
128 return FALSE;
129
130 /* calculate position for the data of the first item */
131 lstDataPos = ((lstItemCount + 1) * sizeof(UINT_PTR)) +
132 (DWORD_PTR)mswBufferEndPtr(mswBuf);
133 /* add ptrofs */
134 lstDataPos += ptrofs;
135
136 /* write array of Pointer to data */
137 for (i1 = 0; i1 < lstItemCount; i1++)
138 {
139 if (!mswBufferAppendPtr(mswBuf, (void*)lstDataPos))
140 return FALSE;
141
142 lstDataPos += sizeof(UINT_PTR);
143 }
144
145 /* end of list */
146 if (!mswBufferAppendPtr(mswBuf, NULL))
147 return FALSE;
148
149 /* write data */
150 ptrSrcLstPos = (UINT_PTR*)lst;
151 for (i1 = 0; i1 < lstItemCount; i1++)
152 {
153 mswBufferAppend(mswBuf, *(BYTE**)ptrSrcLstPos, itemByteLength);
154 ptrSrcLstPos++;
155 }
156 return mswBuf->bufok;
157 }
158
159 BOOL
mswBufferAppendStrLstA(_Inout_ PMSW_BUFFER mswBuf,_In_ void ** lst,_In_opt_ int ptrofs)160 mswBufferAppendStrLstA(_Inout_ PMSW_BUFFER mswBuf,
161 _In_ void **lst,
162 _In_opt_ int ptrofs)
163 {
164 DWORD lstItemLen[MAX_ARRAY_SIZE];
165 DWORD lstItemCount;
166 DWORD lstByteSize;
167 DWORD_PTR lstDataPos;
168 DWORD lstDataSize;
169 DWORD i1;
170 UINT_PTR *ptrSrcLstPos;
171
172 /* calculate size of list */
173 ptrSrcLstPos = (UINT_PTR*)lst;
174 lstItemCount = 0;
175 lstDataSize = 0;
176
177 while (*ptrSrcLstPos != (UINT_PTR)NULL)
178 {
179 if (lstItemCount >= MAX_ARRAY_SIZE)
180 return FALSE;
181
182 i1 = strlen((char*)*ptrSrcLstPos) + sizeof(char);
183 lstItemLen[lstItemCount] = i1;
184 lstItemCount++;
185 lstDataSize += i1;
186 ptrSrcLstPos++;
187 }
188
189 lstByteSize = ((lstItemCount + 1) * sizeof(UINT_PTR)) + /* item-pointer + null-ptr (for end) */
190 lstDataSize; /* item-data */
191
192 if (mswBuf->bytesUsed + lstByteSize > mswBuf->bytesMax)
193 return FALSE;
194
195 /* calculate position for the data of the first item */
196 lstDataPos = ((lstItemCount + 1) * sizeof(UINT_PTR)) +
197 (DWORD_PTR)mswBufferEndPtr(mswBuf);
198
199 /* add ptrofs */
200 lstDataPos += ptrofs;
201
202 for (i1 = 0; i1 < lstItemCount; i1++)
203 {
204 if (!mswBufferAppendPtr(mswBuf, (void*)lstDataPos))
205 return FALSE;
206
207 lstDataPos += lstItemLen[i1];
208 }
209
210 /* end of list */
211 if (!mswBufferAppendPtr(mswBuf, NULL))
212 return FALSE;
213
214 /* write data */
215 ptrSrcLstPos = (UINT_PTR*)lst;
216 for (i1 = 0; i1 < lstItemCount; i1++)
217 {
218 if (!mswBufferAppendStrA(mswBuf, *(char**)ptrSrcLstPos))
219 return FALSE;
220
221 ptrSrcLstPos++;
222 }
223 return mswBuf->bufok;
224 }
225
226 BOOL
mswBufferAppendBlob_Hostent(_Inout_ PMSW_BUFFER mswBuf,_Inout_ LPWSAQUERYSETW lpRes,_In_ char ** hostAliasesA,_In_ char * hostnameA,_In_ DWORD ip4addr)227 mswBufferAppendBlob_Hostent(_Inout_ PMSW_BUFFER mswBuf,
228 _Inout_ LPWSAQUERYSETW lpRes,
229 _In_ char** hostAliasesA,
230 _In_ char* hostnameA,
231 _In_ DWORD ip4addr)
232 {
233 PHOSTENT phe;
234 void* lst[2];
235 BYTE* bytesOfs;
236
237 /* blob */
238 lpRes->lpBlob = (LPBLOB)mswBufferEndPtr(mswBuf);
239
240 if (!mswBufferIncUsed(mswBuf, sizeof(*lpRes->lpBlob)))
241 return FALSE;
242
243 /* cbSize will be set later */
244 lpRes->lpBlob->cbSize = 0;
245 lpRes->lpBlob->pBlobData = mswBufferEndPtr(mswBuf);
246
247 /* hostent */
248 phe = (PHOSTENT)lpRes->lpBlob->pBlobData;
249 bytesOfs = mswBufferEndPtr(mswBuf);
250
251 if (!mswBufferIncUsed(mswBuf, sizeof(*phe)))
252 return FALSE;
253
254 phe->h_addrtype = AF_INET;
255 phe->h_length = 4; /* 4 Byte (IPv4) */
256
257 /* aliases */
258 phe->h_aliases = (char**)(mswBufferEndPtr(mswBuf) - bytesOfs);
259
260 if (hostAliasesA)
261 {
262 if (!mswBufferAppendStrLstA(mswBuf,
263 (void**)hostAliasesA,
264 -(LONG_PTR)bytesOfs))
265 return FALSE;
266 }
267 else
268 {
269 if (!mswBufferAppendPtr(mswBuf, NULL))
270 return FALSE;
271 }
272
273 /* addr_list */
274 RtlZeroMemory(lst, sizeof(lst));
275
276 lst[0] = (void*)&ip4addr;
277
278 phe->h_addr_list = (char**)(mswBufferEndPtr(mswBuf) - bytesOfs);
279
280 if (!mswBufferAppendLst(mswBuf, lst, 4, -(LONG_PTR)bytesOfs))
281 return FALSE;
282
283 /* name */
284 phe->h_name = (char*)(mswBufferEndPtr(mswBuf) - bytesOfs);
285
286 if (!mswBufferAppendStrA(mswBuf, hostnameA))
287 return FALSE;
288
289 lpRes->lpBlob->cbSize = (DWORD)(mswBufferEndPtr(mswBuf) - bytesOfs);
290 return mswBuf->bufok;
291 }
292
293 BOOL
mswBufferAppendBlob_Servent(_Inout_ PMSW_BUFFER mswBuf,_Inout_ LPWSAQUERYSETW lpRes,_In_ char * serviceNameA,_In_ char ** serviceAliasesA,_In_ char * protocolNameA,_In_ WORD port)294 mswBufferAppendBlob_Servent(_Inout_ PMSW_BUFFER mswBuf,
295 _Inout_ LPWSAQUERYSETW lpRes,
296 _In_ char* serviceNameA,
297 _In_ char** serviceAliasesA,
298 _In_ char* protocolNameA,
299 _In_ WORD port)
300 {
301 PSERVENT pse;
302 BYTE* bytesOfs;
303
304 /* blob */
305 lpRes->lpBlob = (LPBLOB)mswBufferEndPtr(mswBuf);
306
307 if (!mswBufferIncUsed(mswBuf, sizeof(*lpRes->lpBlob)))
308 return FALSE;
309
310 lpRes->lpBlob->cbSize = 0;//later
311 lpRes->lpBlob->pBlobData = mswBufferEndPtr(mswBuf);
312
313 /* servent */
314 pse = (LPSERVENT)lpRes->lpBlob->pBlobData;
315 bytesOfs = mswBufferEndPtr(mswBuf);
316
317 if (!mswBufferIncUsed(mswBuf, sizeof(*pse)))
318 return FALSE;
319
320 pse->s_aliases = (char**)(mswBufferEndPtr(mswBuf) - bytesOfs);
321
322 if (serviceAliasesA)
323 {
324 if (!mswBufferAppendStrLstA(mswBuf,
325 (void**)serviceAliasesA,
326 -(LONG_PTR)bytesOfs))
327 return FALSE;
328 }
329 else
330 {
331 if (!mswBufferAppendPtr(mswBuf, NULL))
332 return FALSE;
333 }
334
335 pse->s_name = (char*)(mswBufferEndPtr(mswBuf) - bytesOfs);
336
337 if (!mswBufferAppendStrA(mswBuf, serviceNameA))
338 return FALSE;
339
340 pse->s_port = htons(port);
341
342 pse->s_proto = (char*)(mswBufferEndPtr(mswBuf) - bytesOfs);
343
344 if (!mswBufferAppendStrA(mswBuf, protocolNameA))
345 return FALSE;
346
347 lpRes->lpBlob->cbSize = (DWORD)(mswBufferEndPtr(mswBuf) - bytesOfs);
348 return mswBuf->bufok;
349 }
350
351 BOOL
mswBufferAppendAddr_AddrInfoW(_Inout_ PMSW_BUFFER mswBuf,_Inout_ LPWSAQUERYSETW lpRes,_In_ DWORD ip4addr)352 mswBufferAppendAddr_AddrInfoW(_Inout_ PMSW_BUFFER mswBuf,
353 _Inout_ LPWSAQUERYSETW lpRes,
354 _In_ DWORD ip4addr)
355 {
356 LPCSADDR_INFO paddrinfo;
357 LPSOCKADDR_IN psa;
358
359 lpRes->dwNumberOfCsAddrs = 1;
360 lpRes->lpcsaBuffer = (LPCSADDR_INFO)mswBufferEndPtr(mswBuf);
361
362 paddrinfo = lpRes->lpcsaBuffer;
363
364 if (!mswBufferIncUsed(mswBuf, sizeof(*paddrinfo)))
365 return FALSE;
366
367 paddrinfo->LocalAddr.lpSockaddr = (LPSOCKADDR)mswBufferEndPtr(mswBuf);
368
369 if (!mswBufferIncUsed(mswBuf, sizeof(*paddrinfo->LocalAddr.lpSockaddr)))
370 return FALSE;
371
372 paddrinfo->RemoteAddr.lpSockaddr = (LPSOCKADDR)mswBufferEndPtr(mswBuf);
373
374 if (!mswBufferIncUsed(mswBuf, sizeof(*paddrinfo->RemoteAddr.lpSockaddr)))
375 return FALSE;
376
377 paddrinfo->iSocketType = SOCK_DGRAM;
378 paddrinfo->iProtocol = IPPROTO_UDP;
379
380 psa = (LPSOCKADDR_IN)paddrinfo->LocalAddr.lpSockaddr;
381 paddrinfo->LocalAddr.iSockaddrLength = sizeof(*psa);
382 psa->sin_family = AF_INET;
383 psa->sin_port = 0;
384 psa->sin_addr.s_addr = 0;
385 RtlZeroMemory(psa->sin_zero, sizeof(psa->sin_zero));
386
387 psa = (LPSOCKADDR_IN)paddrinfo->RemoteAddr.lpSockaddr;
388 paddrinfo->RemoteAddr.iSockaddrLength = sizeof(*psa);
389 psa->sin_family = AF_INET;
390 psa->sin_port = 0;
391 psa->sin_addr.s_addr = ip4addr;
392 RtlZeroMemory(psa->sin_zero, sizeof(psa->sin_zero));
393
394 return TRUE;
395 }
396
397 /* ansicode <-> unicode */
398 WCHAR*
StrA2WHeapAlloc(_In_opt_ HANDLE hHeap,_In_ char * aStr)399 StrA2WHeapAlloc(_In_opt_ HANDLE hHeap,
400 _In_ char* aStr)
401 {
402 int aStrByteLen;
403 int wStrByteLen;
404 int charLen;
405 int ret;
406 WCHAR* wStr;
407
408 if (aStr == NULL)
409 return NULL;
410
411 charLen = strlen(aStr) + 1;
412
413 aStrByteLen = (charLen * sizeof(char));
414 wStrByteLen = (charLen * sizeof(WCHAR));
415
416 if (hHeap == 0)
417 hHeap = GetProcessHeap();
418
419 wStr = HeapAlloc(hHeap, 0, wStrByteLen);
420 if (wStr == NULL)
421 {
422 HeapFree(hHeap, 0, wStr);
423 return NULL;
424 }
425
426 ret = MultiByteToWideChar(CP_ACP,
427 0,
428 aStr,
429 aStrByteLen,
430 wStr,
431 charLen);
432
433 if (ret != charLen)
434 {
435 HeapFree(hHeap, 0, wStr);
436 return NULL;
437 }
438 return wStr;
439 }
440
441 char*
StrW2AHeapAlloc(_In_opt_ HANDLE hHeap,_In_ WCHAR * wStr)442 StrW2AHeapAlloc(_In_opt_ HANDLE hHeap,
443 _In_ WCHAR* wStr)
444 {
445 int charLen;
446 int aStrByteLen;
447 int ret;
448 char* aStr;
449
450 if (wStr == NULL)
451 return NULL;
452
453 charLen = wcslen(wStr) + 1;
454
455 aStrByteLen = (charLen * sizeof(char));
456
457 if (hHeap == 0)
458 hHeap = GetProcessHeap();
459
460 aStr = HeapAlloc(hHeap, 0, aStrByteLen);
461 if (aStr == NULL)
462 {
463 HeapFree(hHeap, 0, aStr);
464 return NULL;
465 }
466
467 ret = WideCharToMultiByte(CP_ACP,
468 0,
469 wStr,
470 charLen,
471 aStr,
472 aStrByteLen,
473 NULL,
474 NULL);
475 if (ret != aStrByteLen)
476 {
477 HeapFree(hHeap, 0, aStr);
478 return NULL;
479 }
480 return aStr;
481 }
482
483 WCHAR*
StrCpyHeapAllocW(_In_opt_ HANDLE hHeap,_In_ WCHAR * wStr)484 StrCpyHeapAllocW(_In_opt_ HANDLE hHeap,
485 _In_ WCHAR* wStr)
486 {
487 size_t chLen;
488 size_t bLen;
489 WCHAR* resW;
490
491 if (wStr == NULL)
492 return NULL;
493
494 if (hHeap == 0)
495 hHeap = GetProcessHeap();
496
497 chLen = wcslen(wStr);
498
499 bLen = (chLen + 1) * sizeof(WCHAR);
500
501 resW = HeapAlloc(hHeap, 0, bLen);
502 RtlCopyMemory(resW, wStr, bLen);
503 return resW;
504 }
505
506 char*
StrCpyHeapAllocA(_In_opt_ HANDLE hHeap,_In_ char * aStr)507 StrCpyHeapAllocA(_In_opt_ HANDLE hHeap,
508 _In_ char* aStr)
509 {
510 size_t chLen;
511 size_t bLen;
512 char* resA;
513
514 if (aStr == NULL)
515 return NULL;
516
517 if (hHeap == 0)
518 hHeap = GetProcessHeap();
519
520 chLen = strlen(aStr);
521
522 bLen = (chLen + 1) * sizeof(char);
523
524 resA = HeapAlloc(hHeap, 0, bLen);
525 RtlCopyMemory(resA, aStr, bLen);
526 return resA;
527 }
528
529 char**
StrAryCpyHeapAllocA(_In_opt_ HANDLE hHeap,_In_ char ** aStrAry)530 StrAryCpyHeapAllocA(_In_opt_ HANDLE hHeap,
531 _In_ char** aStrAry)
532 {
533 char** aSrcPtr;
534 char** aDstPtr;
535 char* aDstNextStr;
536 DWORD aStrByteLen[MAX_ARRAY_SIZE];
537 size_t bLen;
538 size_t bItmLen;
539 int aCount;
540 int i1;
541 char** resA;
542
543 if (hHeap == 0)
544 hHeap = GetProcessHeap();
545
546 /* Calculating size of array ... */
547 aSrcPtr = aStrAry;
548 bLen = 0;
549 aCount = 0;
550
551 while (*aSrcPtr != NULL)
552 {
553 if (aCount >= MAX_ARRAY_SIZE)
554 return NULL;
555
556 bItmLen = strlen(*aSrcPtr) + 1;
557 aStrByteLen[aCount] = bItmLen;
558
559 bLen += sizeof(*aSrcPtr) + bItmLen;
560
561 aSrcPtr++;
562 aCount++;
563 }
564
565 /* size for NULL-terminator */
566 bLen += sizeof(*aSrcPtr);
567
568 /* get memory */
569 resA = HeapAlloc(hHeap, 0, bLen);
570
571 /* copy data */
572 aSrcPtr = aStrAry;
573 aDstPtr = resA;
574
575 /* pos for the first string */
576 aDstNextStr = (char*)(resA + aCount + 1);
577 for (i1 = 0; i1 < aCount; i1++)
578 {
579 bItmLen = aStrByteLen[i1];
580
581 *aDstPtr = aDstNextStr;
582 RtlCopyMemory(*aDstPtr, *aSrcPtr, bItmLen);
583
584 aDstNextStr = (char*)((DWORD_PTR)aDstNextStr + (DWORD)bItmLen);
585 aDstPtr++;
586 aSrcPtr++;
587 }
588
589 /* terminate with NULL */
590 *aDstPtr = NULL;
591
592 return resA;
593 }
594
595 char**
StrAryCpyHeapAllocWToA(_In_opt_ HANDLE hHeap,_In_ WCHAR ** wStrAry)596 StrAryCpyHeapAllocWToA(_In_opt_ HANDLE hHeap,
597 _In_ WCHAR** wStrAry)
598 {
599 WCHAR** wSrcPtr;
600 char** aDstPtr;
601 char* aDstNextStr;
602 DWORD aStrByteLen[MAX_ARRAY_SIZE];
603 int bLen;
604 int bItmLen;
605 int aCount;
606 int i1;
607 char** resA;
608 int ret;
609 char* aStr;
610
611 if (hHeap == 0)
612 hHeap = GetProcessHeap();
613
614 /* Calculating size of array ... */
615 wSrcPtr = wStrAry;
616 bLen = 0;
617 aCount = 0;
618
619 while (*wSrcPtr != NULL)
620 {
621 if (aCount >= MAX_ARRAY_SIZE)
622 return NULL;
623
624 bItmLen = wcslen(*wSrcPtr) + 1;
625 aStrByteLen[aCount] = bItmLen;
626
627 bLen += sizeof(*wSrcPtr) + bItmLen;
628
629 wSrcPtr++;
630 aCount++;
631 }
632
633 /* size for NULL-terminator */
634 bLen += sizeof(*wSrcPtr);
635
636 /* get memory */
637 resA = HeapAlloc(hHeap, 0, bLen);
638
639 /* copy data */
640 wSrcPtr = wStrAry;
641 aDstPtr = resA;
642
643 /* pos for the first string */
644 aDstNextStr = (char*)(resA + aCount + 1);
645 for (i1 = 0; i1 < aCount; i1++)
646 {
647 bItmLen = aStrByteLen[i1];
648
649 *aDstPtr = aDstNextStr;
650
651 aStr = HeapAlloc(hHeap, 0, bItmLen);
652 if (aStr == NULL)
653 {
654 HeapFree(hHeap, 0, aStr);
655 return NULL;
656 }
657
658 ret = WideCharToMultiByte(CP_ACP,
659 0,
660 *wSrcPtr,
661 bItmLen,
662 aStr,
663 bItmLen,
664 NULL,
665 NULL);
666 if (ret != bItmLen)
667 {
668 HeapFree(hHeap, 0, aStr);
669 return NULL;
670 }
671 RtlCopyMemory(*aDstPtr, aStr, bItmLen);
672 HeapFree(hHeap, 0, aStr);
673
674 aDstNextStr = (char*)((DWORD_PTR)aDstNextStr + (DWORD)bItmLen);
675 aDstPtr++;
676 wSrcPtr++;
677 }
678
679 /* terminate with NULL */
680 *aDstPtr = NULL;
681
682 return resA;
683 }
684