xref: /reactos/dll/win32/ws2_32/src/qshelpr.c (revision 682f85ad)
1 /*
2  * COPYRIGHT:   See COPYING in the top level directory
3  * PROJECT:     ReactOS WinSock 2 API
4  * FILE:        dll/win32/ws2_32/src/qshelpr.c
5  * PURPOSE:     Query Set Conversion/Packing Helpers
6  * PROGRAMMER:  Alex Ionescu (alex@relsoft.net)
7  */
8 
9 /* INCLUDES ******************************************************************/
10 
11 #include <ws2_32.h>
12 
13 #define NDEBUG
14 #include <debug.h>
15 
16 /* FUNCTIONS *****************************************************************/
17 
18 LPSTR
19 WSAAPI
AnsiDupFromUnicode(IN LPCWSTR UnicodeString)20 AnsiDupFromUnicode(IN LPCWSTR UnicodeString)
21 {
22     INT Length = 0;
23     BOOL GoOn = TRUE;
24     LPSTR DuplicatedString = NULL;
25     INT ReturnValue;
26 
27     /* Start a loop (which should only run twice) */
28     while (GoOn)
29     {
30         /* Call the conversion function */
31         ReturnValue = WideCharToMultiByte(CP_ACP,
32                                           0,
33                                           UnicodeString,
34                                           -1,
35                                           DuplicatedString,
36                                           Length,
37                                           NULL,
38                                           NULL);
39         if (ReturnValue > Length)
40         {
41             /* This is the first loop, and we have the real size now */
42             Length = ReturnValue;
43 
44             /* Allocate buffer for it */
45             DuplicatedString = HeapAlloc(WsSockHeap, 0, Length);
46             if (!DuplicatedString) GoOn = FALSE;
47         }
48         else if (ReturnValue > 0)
49         {
50             /* The second loop was successful and we have the string */
51             GoOn = FALSE;
52         }
53         else
54         {
55             /* Some weird error happened */
56             if (DuplicatedString) HeapFree(WsSockHeap, 0, DuplicatedString);
57             DuplicatedString = NULL;
58             GoOn = FALSE;
59         }
60     }
61 
62     /* Return the duplicate */
63     return DuplicatedString;
64 }
65 
66 LPWSTR
67 WSAAPI
UnicodeDupFromAnsi(IN LPCSTR AnsiString)68 UnicodeDupFromAnsi(IN LPCSTR AnsiString)
69 {
70     INT Length = 0;
71     BOOL GoOn = TRUE;
72     LPWSTR DuplicatedString = NULL;
73     INT ReturnValue;
74 
75     /* Start a loop (which should only run twice) */
76     while (GoOn)
77     {
78         /* Call the conversion function */
79         ReturnValue = MultiByteToWideChar(CP_ACP,
80                                           0,
81                                           AnsiString,
82                                           -1,
83                                           DuplicatedString,
84                                           Length);
85         if (ReturnValue > Length)
86         {
87             /* This is the first loop, and we have the real size now */
88             Length = ReturnValue;
89 
90             /* Allocate buffer for it */
91             DuplicatedString = HeapAlloc(WsSockHeap, 0, Length * sizeof(WCHAR));
92             if (!DuplicatedString) GoOn = FALSE;
93         }
94         else if (ReturnValue > 0)
95         {
96             /* The second loop was successful and we have the string */
97             GoOn = FALSE;
98         }
99         else
100         {
101             /* Some weird error happened */
102             if (DuplicatedString) HeapFree(WsSockHeap, 0, DuplicatedString);
103             DuplicatedString = NULL;
104             GoOn = FALSE;
105         }
106     }
107 
108     /* Return the duplicate */
109     return DuplicatedString;
110 }
111 
112 SIZE_T
113 WSAAPI
ComputeStringSize(IN LPSTR String,IN BOOLEAN IsUnicode)114 ComputeStringSize(IN LPSTR String,
115                   IN BOOLEAN IsUnicode)
116 {
117     /* Return the size of the string, in bytes, including null-char */
118     return (IsUnicode) ? (wcslen((LPWSTR)String) + 1 ) * sizeof(WCHAR) :
119                           strlen(String) + sizeof(CHAR);
120 }
121 
122 SIZE_T
123 WSAAPI
ComputeQuerySetSize(IN LPWSAQUERYSETA AnsiSet,IN BOOLEAN IsUnicode)124 ComputeQuerySetSize(IN LPWSAQUERYSETA AnsiSet,
125                     IN BOOLEAN IsUnicode)
126 {
127     SIZE_T Size = sizeof(WSAQUERYSETA);
128     //LPWSAQUERYSETW UnicodeSet = (LPWSAQUERYSETW)AnsiSet;
129     DWORD i;
130 
131     /* Check for instance name */
132     if (AnsiSet->lpszServiceInstanceName)
133     {
134         /* Add its size */
135         Size += ComputeStringSize(AnsiSet->lpszServiceInstanceName, IsUnicode);
136     }
137 
138     /* Check for Service Class ID */
139     if (AnsiSet->lpServiceClassId)
140     {
141         /* Align the current size and add GUID size */
142         Size = (Size + 3) & ~3;
143         Size += sizeof(GUID);
144     }
145 
146     /* Check for version data */
147     if (AnsiSet->lpVersion)
148     {
149         /* Align the current size and add GUID size */
150         Size = (Size + 3) & ~3;
151         Size += sizeof(WSAVERSION);
152     }
153 
154     /* Check for comment */
155     if (AnsiSet->lpszComment)
156     {
157         /* Align the current size and add string size */
158         Size = (Size + 1) & ~1;
159         Size += ComputeStringSize(AnsiSet->lpszComment, IsUnicode);
160     }
161 
162     /* Check for Provider ID */
163     if (AnsiSet->lpNSProviderId)
164     {
165         /* Align the current size and add GUID size */
166         Size = (Size + 3) & ~3;
167         Size += sizeof(GUID);
168     }
169 
170     /* Check for context */
171     if (AnsiSet->lpszContext)
172     {
173         /* Align the current size and add string size */
174         Size = (Size + 1) & ~1;
175         Size += ComputeStringSize(AnsiSet->lpszContext, IsUnicode);
176     }
177 
178     /* Check for query string */
179     if (AnsiSet->lpszQueryString)
180     {
181         /* Align the current size and add string size */
182         Size = (Size + 1) & ~1;
183         Size += ComputeStringSize(AnsiSet->lpszQueryString, IsUnicode);
184     }
185 
186     /* Check for AF Protocol data */
187     if (AnsiSet->lpafpProtocols)
188     {
189         /* Align the current size and add AFP size */
190         Size = (Size + 3) & ~3;
191         Size += sizeof(AFPROTOCOLS) * AnsiSet->dwNumberOfProtocols;
192     }
193 
194     /* Check for CSADDR buffer */
195     if (AnsiSet->lpcsaBuffer)
196     {
197         /* Align the current size */
198         Size = (Size + 3) & ~3;
199 
200         /* Loop all the addresses in the array */
201         for (i = 0; i < AnsiSet->dwNumberOfCsAddrs; i++)
202         {
203             /* Check for local sockaddr */
204             if (AnsiSet->lpcsaBuffer[i].LocalAddr.lpSockaddr)
205             {
206                 /* Align the current size and add the sockaddr's length */
207                 Size = (Size + 3) & ~3;
208                 Size += AnsiSet->lpcsaBuffer[i].LocalAddr.iSockaddrLength;
209             }
210             /* Check for remote sockaddr */
211             if (AnsiSet->lpcsaBuffer[i].RemoteAddr.lpSockaddr)
212             {
213                 /* Align the current size and add the sockaddr's length */
214                 Size = (Size + 3) & ~3;
215                 Size += AnsiSet->lpcsaBuffer[i].RemoteAddr.iSockaddrLength;
216             }
217 
218             /* Add the sockaddr size itself */
219             Size += sizeof(CSADDR_INFO);
220         }
221     }
222 
223     /* Check for blob data */
224     if (AnsiSet->lpBlob)
225     {
226         /* Align the current size and add blob size */
227         Size = (Size + 3) & ~3;
228         Size += sizeof(BLOB);
229 
230         /* Also add the actual blob data size, if it exists */
231         if (AnsiSet->lpBlob) Size += AnsiSet->lpBlob->cbSize;
232     }
233 
234     /* Return the total size */
235     return Size;
236 }
237 
238 SIZE_T
239 WSAAPI
WSAComputeQuerySetSizeA(IN LPWSAQUERYSETA AnsiSet)240 WSAComputeQuerySetSizeA(IN LPWSAQUERYSETA AnsiSet)
241 {
242     /* Call the generic helper */
243     return ComputeQuerySetSize(AnsiSet, FALSE);
244 }
245 
246 SIZE_T
247 WSAAPI
WSAComputeQuerySetSizeW(IN LPWSAQUERYSETW UnicodeSet)248 WSAComputeQuerySetSizeW(IN LPWSAQUERYSETW UnicodeSet)
249 {
250     /* Call the generic helper */
251     return ComputeQuerySetSize((LPWSAQUERYSETA)UnicodeSet, TRUE);
252 }
253 
254 PVOID
255 WSAAPI
WsBufferAllocate(IN PWS_BUFFER Buffer,IN SIZE_T Size,IN DWORD Align)256 WsBufferAllocate(IN PWS_BUFFER Buffer,
257                  IN SIZE_T Size,
258                  IN DWORD Align)
259 {
260     PVOID NewPosition;
261 
262     /* Align the current usage */
263     Buffer->BytesUsed = (Buffer->BytesUsed + Align - 1) & ~(Align - 1);
264 
265     /* Update our location */
266     NewPosition = (PVOID)(Buffer->Position + Buffer->BytesUsed);
267 
268     /* Update the usage */
269     Buffer->BytesUsed += Size;
270 
271     /* Return new location */
272     return NewPosition;
273 }
274 
275 VOID
276 WSAAPI
CopyBlobIndirect(IN PWS_BUFFER Buffer,IN OUT LPBLOB RelativeBlob,IN LPBLOB Blob)277 CopyBlobIndirect(IN PWS_BUFFER Buffer,
278                  IN OUT LPBLOB RelativeBlob,
279                  IN LPBLOB Blob)
280 {
281     /* Make sure we have blob data */
282     if ((Blob->pBlobData) && (Blob->cbSize))
283     {
284         /* Allocate and copy the blob data */
285         RelativeBlob->pBlobData = WsBufferAllocate(Buffer,
286                                                    Blob->cbSize,
287                                                    sizeof(PVOID));
288         RtlCopyMemory(RelativeBlob->pBlobData,
289                       Blob->pBlobData,
290                       Blob->cbSize);
291     }
292 }
293 
294 VOID
295 WSAAPI
CopyAddrInfoArrayIndirect(IN PWS_BUFFER Buffer,IN OUT LPCSADDR_INFO RelativeCsaddr,IN DWORD Addresses,IN LPCSADDR_INFO Csaddr)296 CopyAddrInfoArrayIndirect(IN PWS_BUFFER Buffer,
297                           IN OUT LPCSADDR_INFO RelativeCsaddr,
298                           IN DWORD Addresses,
299                           IN LPCSADDR_INFO Csaddr)
300 {
301     DWORD i;
302 
303     /* Loop for every address inside */
304     for (i = 0; i < Addresses; i++)
305     {
306         /* Check for a local address */
307         if ((Csaddr[i].LocalAddr.lpSockaddr) &&
308             (Csaddr[i].LocalAddr.iSockaddrLength))
309         {
310             /* Allocate and copy the address */
311             RelativeCsaddr[i].LocalAddr.lpSockaddr =
312                 WsBufferAllocate(Buffer,
313                                  Csaddr[i].LocalAddr.iSockaddrLength,
314                                  sizeof(PVOID));
315             RtlCopyMemory(RelativeCsaddr[i].LocalAddr.lpSockaddr,
316                           Csaddr[i].LocalAddr.lpSockaddr,
317                           Csaddr[i].LocalAddr.iSockaddrLength);
318         }
319         else
320         {
321             /* Nothing in this address */
322             Csaddr[i].LocalAddr.lpSockaddr = NULL;
323             Csaddr[i].LocalAddr.iSockaddrLength = 0;
324         }
325 
326         /* Check for a remote address */
327         if ((Csaddr[i].RemoteAddr.lpSockaddr) &&
328             (Csaddr[i].RemoteAddr.iSockaddrLength))
329         {
330             /* Allocate and copy the address */
331             RelativeCsaddr[i].RemoteAddr.lpSockaddr =
332                 WsBufferAllocate(Buffer,
333                                  Csaddr[i].RemoteAddr.iSockaddrLength,
334                                  sizeof(PVOID));
335             RtlCopyMemory(RelativeCsaddr[i].RemoteAddr.lpSockaddr,
336                           Csaddr[i].RemoteAddr.lpSockaddr,
337                           Csaddr[i].RemoteAddr.iSockaddrLength);
338         }
339         else
340         {
341             /* Nothing in this address */
342             Csaddr[i].RemoteAddr.lpSockaddr = NULL;
343             Csaddr[i].RemoteAddr.iSockaddrLength = 0;
344         }
345     }
346 }
347 
348 VOID
349 WSAAPI
CopyQuerySetIndirectA(IN PWS_BUFFER Buffer,IN OUT LPWSAQUERYSETA RelativeSet,IN LPWSAQUERYSETA AnsiSet)350 CopyQuerySetIndirectA(IN PWS_BUFFER Buffer,
351                       IN OUT LPWSAQUERYSETA RelativeSet,
352                       IN LPWSAQUERYSETA AnsiSet)
353 {
354     LPSTR AnsiString;
355 
356     /* Get the service name */
357     AnsiString = AnsiSet->lpszServiceInstanceName;
358     if (AnsiString)
359     {
360         /* One exists, allocate a space in the buffer for it */
361         RelativeSet->lpszServiceInstanceName = WsBufferAllocate(Buffer,
362                                                                 strlen(AnsiString) + 1,
363                                                                 sizeof(CHAR));
364         /* Copy it into the buffer */
365         strcpy(RelativeSet->lpszServiceInstanceName, AnsiString);
366     }
367     else
368     {
369         /* Nothing in the buffer */
370         RelativeSet->lpszServiceInstanceName = NULL;
371     }
372 
373     /* Check for the service class ID */
374     if (AnsiSet->lpServiceClassId)
375     {
376         /* One exists, allocate a space in the buffer for it */
377         RelativeSet->lpServiceClassId = WsBufferAllocate(Buffer,
378                                                          sizeof(GUID),
379                                                          sizeof(PVOID));
380         /* Copy it into the buffer */
381         *(RelativeSet->lpServiceClassId) = *(AnsiSet->lpServiceClassId);
382     }
383     else
384     {
385         /* Nothing in the buffer */
386         RelativeSet->lpServiceClassId = NULL;
387     }
388 
389     /* Get the version data */
390     if (AnsiSet->lpVersion)
391     {
392         /* One exists, allocate a space in the buffer for it */
393         RelativeSet->lpVersion = WsBufferAllocate(Buffer,
394                                                   sizeof(WSAVERSION),
395                                                   sizeof(PVOID));
396         /* Copy it into the buffer */
397         *(RelativeSet->lpVersion) = *(AnsiSet->lpVersion);
398     }
399     else
400     {
401         /* Nothing in the buffer */
402         RelativeSet->lpVersion = NULL;
403     }
404 
405     /* Get the comment */
406     AnsiString = AnsiSet->lpszComment;
407     if (AnsiString)
408     {
409         /* One exists, allocate a space in the buffer for it */
410         RelativeSet->lpszComment = WsBufferAllocate(Buffer,
411                                                     strlen(AnsiString) + 1,
412                                                     sizeof(CHAR));
413         /* Copy it into the buffer */
414         strcpy(RelativeSet->lpszComment, AnsiString);
415     }
416     else
417     {
418         /* Nothing in the buffer */
419         RelativeSet->lpszComment = NULL;
420     }
421 
422     /* Get the NS Provider ID */
423     if (AnsiSet->lpNSProviderId)
424     {
425         /* One exists, allocate a space in the buffer for it */
426         RelativeSet->lpNSProviderId = WsBufferAllocate(Buffer,
427                                                        sizeof(GUID),
428                                                        sizeof(PVOID));
429         /* Copy it into the buffer */
430         *(RelativeSet->lpNSProviderId) = *(AnsiSet->lpNSProviderId);
431     }
432     else
433     {
434         /* Nothing in the buffer */
435         RelativeSet->lpNSProviderId = NULL;
436     }
437 
438     /* Get the context */
439     AnsiString = AnsiSet->lpszContext;
440     if (AnsiString)
441     {
442         /* One exists, allocate a space in the buffer for it */
443         RelativeSet->lpszContext = WsBufferAllocate(Buffer,
444                                                     strlen(AnsiString) + 1,
445                                                     sizeof(CHAR));
446         /* Copy it into the buffer */
447         strcpy(RelativeSet->lpszContext, AnsiString);
448     }
449     else
450     {
451         /* Nothing in the buffer */
452         RelativeSet->lpszContext = NULL;
453     }
454 
455     /* Get the query string */
456     AnsiString = AnsiSet->lpszQueryString;
457     if (AnsiString)
458     {
459         /* One exists, allocate a space in the buffer for it */
460         RelativeSet->lpszQueryString = WsBufferAllocate(Buffer,
461                                                         strlen(AnsiString) + 1,
462                                                         sizeof(CHAR));
463         /* Copy it into the buffer */
464         strcpy(RelativeSet->lpszQueryString, AnsiString);
465     }
466     else
467     {
468         /* Nothing in the buffer */
469         RelativeSet->lpszQueryString = NULL;
470     }
471 
472     /* Check for a protocol structure with non-zero protocols */
473     if ((AnsiSet->lpafpProtocols) && (AnsiSet->dwNumberOfProtocols))
474     {
475         /* One exists, allocate space for it */
476         RelativeSet->lpafpProtocols = WsBufferAllocate(Buffer,
477                                                        AnsiSet->dwNumberOfProtocols *
478                                                        sizeof(AFPROTOCOLS),
479                                                        sizeof(PVOID));
480         /* Copy it into the buffer */
481         RtlCopyMemory(RelativeSet->lpafpProtocols,
482                       AnsiSet->lpafpProtocols,
483                       AnsiSet->dwNumberOfProtocols * sizeof(AFPROTOCOLS));
484     }
485     else
486     {
487         /* Nothing in the buffer */
488         RelativeSet->lpafpProtocols = NULL;
489         RelativeSet->dwNumberOfProtocols = 0;
490     }
491 
492     /* Check if we have a CSADDR with addresses inside */
493     if ((AnsiSet->lpcsaBuffer) && (AnsiSet->dwNumberOfCsAddrs))
494     {
495         /* Allocate and copy the CSADDR structure itself */
496         RelativeSet->lpcsaBuffer = WsBufferAllocate(Buffer,
497                                                     AnsiSet->dwNumberOfCsAddrs *
498                                                     sizeof(CSADDR_INFO),
499                                                     sizeof(PVOID));
500 
501         /* Copy it into the buffer */
502         RtlCopyMemory(RelativeSet->lpcsaBuffer,
503                       AnsiSet->lpcsaBuffer,
504                       AnsiSet->dwNumberOfCsAddrs * sizeof(CSADDR_INFO));
505 
506         /* Copy the addresses inside the CSADDR */
507         CopyAddrInfoArrayIndirect(Buffer,
508                                   RelativeSet->lpcsaBuffer,
509                                   AnsiSet->dwNumberOfCsAddrs,
510                                   AnsiSet->lpcsaBuffer);
511     }
512     else
513     {
514         /* Nothing in the buffer */
515         RelativeSet->lpcsaBuffer = NULL;
516         RelativeSet->dwNumberOfCsAddrs = 0;
517     }
518 
519     /* Check for blob data */
520     if (AnsiSet->lpBlob)
521     {
522         /* Allocate and copy the blob itself */
523         RelativeSet->lpBlob = WsBufferAllocate(Buffer,
524                                                sizeof(BLOB),
525                                                sizeof(PVOID));
526         *(RelativeSet->lpBlob) = *(AnsiSet->lpBlob);
527 
528         /* Copy the data inside the blob */
529         CopyBlobIndirect(Buffer, RelativeSet->lpBlob, AnsiSet->lpBlob);
530     }
531     else
532     {
533         /* Nothing in the buffer */
534         RelativeSet->lpBlob = NULL;
535     }
536 }
537 
538 VOID
539 WSAAPI
CopyQuerySetIndirectW(IN PWS_BUFFER Buffer,IN OUT LPWSAQUERYSETW RelativeSet,IN LPWSAQUERYSETW UnicodeSet)540 CopyQuerySetIndirectW(IN PWS_BUFFER Buffer,
541                       IN OUT LPWSAQUERYSETW RelativeSet,
542                       IN LPWSAQUERYSETW UnicodeSet)
543 {
544     LPWSTR UnicodeString;
545 
546     /* Get the service name */
547     UnicodeString = UnicodeSet->lpszServiceInstanceName;
548     if (UnicodeString)
549     {
550         /* One exists, allocate a space in the buffer for it */
551         RelativeSet->lpszServiceInstanceName = WsBufferAllocate(Buffer,
552                                                                 (wcslen(UnicodeString) + 1) *
553                                                                 sizeof(WCHAR),
554                                                                 sizeof(CHAR));
555         /* Copy it into the buffer */
556         wcscpy(RelativeSet->lpszServiceInstanceName, UnicodeString);
557     }
558     else
559     {
560         /* Nothing in the buffer */
561         RelativeSet->lpszServiceInstanceName = NULL;
562     }
563 
564     /* Check for the service class ID */
565     if (UnicodeSet->lpServiceClassId)
566     {
567         /* One exists, allocate a space in the buffer for it */
568         RelativeSet->lpServiceClassId = WsBufferAllocate(Buffer,
569                                                          sizeof(GUID),
570                                                          sizeof(PVOID));
571         /* Copy it into the buffer */
572         *(RelativeSet->lpServiceClassId) = *(UnicodeSet->lpServiceClassId);
573     }
574     else
575     {
576         /* Nothing in the buffer */
577         RelativeSet->lpServiceClassId = NULL;
578     }
579 
580     /* Get the version data */
581     if (UnicodeSet->lpVersion)
582     {
583         /* One exists, allocate a space in the buffer for it */
584         RelativeSet->lpVersion = WsBufferAllocate(Buffer,
585                                                   sizeof(WSAVERSION),
586                                                   sizeof(PVOID));
587         /* Copy it into the buffer */
588         *(RelativeSet->lpVersion) = *(UnicodeSet->lpVersion);
589     }
590     else
591     {
592         /* Nothing in the buffer */
593         RelativeSet->lpVersion = NULL;
594     }
595 
596     /* Get the comment */
597     UnicodeString = UnicodeSet->lpszComment;
598     if (UnicodeString)
599     {
600         /* One exists, allocate a space in the buffer for it */
601         RelativeSet->lpszComment = WsBufferAllocate(Buffer,
602                                                     (wcslen(UnicodeString) + 1) *
603                                                     sizeof(WCHAR),
604                                                     sizeof(CHAR));
605         /* Copy it into the buffer */
606         wcscpy(RelativeSet->lpszComment, UnicodeString);
607     }
608     else
609     {
610         /* Nothing in the buffer */
611         RelativeSet->lpszComment = NULL;
612     }
613 
614     /* Get the NS Provider ID */
615     if (UnicodeSet->lpNSProviderId)
616     {
617         /* One exists, allocate a space in the buffer for it */
618         RelativeSet->lpNSProviderId = WsBufferAllocate(Buffer,
619                                                        sizeof(GUID),
620                                                        sizeof(PVOID));
621         /* Copy it into the buffer */
622         *(RelativeSet->lpNSProviderId) = *(UnicodeSet->lpNSProviderId);
623     }
624     else
625     {
626         /* Nothing in the buffer */
627         RelativeSet->lpNSProviderId = NULL;
628     }
629 
630     /* Get the context */
631     UnicodeString = UnicodeSet->lpszContext;
632     if (UnicodeString)
633     {
634         /* One exists, allocate a space in the buffer for it */
635         RelativeSet->lpszContext = WsBufferAllocate(Buffer,
636                                                     (wcslen(UnicodeString) + 1) *
637                                                     sizeof(WCHAR),
638                                                     sizeof(CHAR));
639         /* Copy it into the buffer */
640         wcscpy(RelativeSet->lpszContext, UnicodeString);
641     }
642     else
643     {
644         /* Nothing in the buffer */
645         RelativeSet->lpszContext = NULL;
646     }
647 
648     /* Get the query string */
649     UnicodeString = UnicodeSet->lpszQueryString;
650     if (UnicodeString)
651     {
652         /* One exists, allocate a space in the buffer for it */
653         RelativeSet->lpszQueryString = WsBufferAllocate(Buffer,
654                                                         (wcslen(UnicodeString) + 1) *
655                                                         sizeof(WCHAR),
656                                                         sizeof(CHAR));
657         /* Copy it into the buffer */
658         wcscpy(RelativeSet->lpszQueryString, UnicodeString);
659     }
660     else
661     {
662         /* Nothing in the buffer */
663         RelativeSet->lpszQueryString = NULL;
664     }
665 
666     /* Check for a protocol structure with non-zero protocols */
667     if ((UnicodeSet->lpafpProtocols) && (UnicodeSet->dwNumberOfProtocols))
668     {
669         /* One exists, allocate space for it */
670         RelativeSet->lpafpProtocols = WsBufferAllocate(Buffer,
671                                                        UnicodeSet->dwNumberOfProtocols *
672                                                        sizeof(AFPROTOCOLS),
673                                                        sizeof(PVOID));
674         /* Copy it into the buffer */
675         RtlCopyMemory(RelativeSet->lpafpProtocols,
676                       UnicodeSet->lpafpProtocols,
677                       UnicodeSet->dwNumberOfProtocols * sizeof(AFPROTOCOLS));
678     }
679     else
680     {
681         /* Nothing in the buffer */
682         RelativeSet->lpafpProtocols = NULL;
683         RelativeSet->dwNumberOfProtocols = 0;
684     }
685 
686     /* Check if we have a CSADDR with addresses inside */
687     if ((UnicodeSet->lpcsaBuffer) && (UnicodeSet->dwNumberOfCsAddrs))
688     {
689         /* Allocate and copy the CSADDR structure itself */
690         RelativeSet->lpcsaBuffer = WsBufferAllocate(Buffer,
691                                                     UnicodeSet->dwNumberOfCsAddrs *
692                                                     sizeof(CSADDR_INFO),
693                                                     sizeof(PVOID));
694 
695         /* Copy it into the buffer */
696         RtlCopyMemory(RelativeSet->lpcsaBuffer,
697                       UnicodeSet->lpcsaBuffer,
698                       UnicodeSet->dwNumberOfCsAddrs * sizeof(CSADDR_INFO));
699 
700         /* Copy the addresses inside the CSADDR */
701         CopyAddrInfoArrayIndirect(Buffer,
702                                   RelativeSet->lpcsaBuffer,
703                                   UnicodeSet->dwNumberOfCsAddrs,
704                                   UnicodeSet->lpcsaBuffer);
705     }
706     else
707     {
708         /* Nothing in the buffer */
709         RelativeSet->lpcsaBuffer = NULL;
710         RelativeSet->dwNumberOfCsAddrs = 0;
711     }
712 
713     /* Check for blob data */
714     if (UnicodeSet->lpBlob)
715     {
716         /* Allocate and copy the blob itself */
717         RelativeSet->lpBlob = WsBufferAllocate(Buffer,
718                                                sizeof(BLOB),
719                                                sizeof(PVOID));
720         *(RelativeSet->lpBlob) = *(UnicodeSet->lpBlob);
721 
722         /* Copy the data inside the blob */
723         CopyBlobIndirect(Buffer, RelativeSet->lpBlob, UnicodeSet->lpBlob);
724     }
725     else
726     {
727         /* Nothing in the buffer */
728         RelativeSet->lpBlob = NULL;
729     }
730 }
731 
732 INT
733 WSAAPI
WSABuildQuerySetBufferA(IN LPWSAQUERYSETA AnsiSet,IN SIZE_T BufferSize,OUT LPWSAQUERYSETA RelativeSet)734 WSABuildQuerySetBufferA(IN LPWSAQUERYSETA AnsiSet,
735                         IN SIZE_T BufferSize,
736                         OUT LPWSAQUERYSETA RelativeSet)
737 {
738     INT ErrorCode = ERROR_SUCCESS;
739     SIZE_T SetSize;
740     WS_BUFFER Buffer;
741     LPWSAQUERYSETA NewSet;
742 
743     /* Find out how big the set really is */
744     SetSize = WSAComputeQuerySetSizeA(AnsiSet);
745     if (SetSize <= BufferSize)
746     {
747         /* Configure the buffer */
748         Buffer.Position = (ULONG_PTR)RelativeSet;
749         Buffer.MaxSize = SetSize;
750         Buffer.BytesUsed = 0;
751 
752         /* Copy the set itself into the buffer */
753         NewSet = WsBufferAllocate(&Buffer, sizeof(*AnsiSet), sizeof(PVOID));
754         *NewSet = *AnsiSet;
755 
756         /* Now copy the data inside */
757         CopyQuerySetIndirectA(&Buffer, NewSet, AnsiSet);
758     }
759     else
760     {
761         /* We failed */
762         ErrorCode = SOCKET_ERROR;
763     }
764 
765     /* Return to caller */
766     return ErrorCode;
767 }
768 
769 INT
770 WSAAPI
WSABuildQuerySetBufferW(IN LPWSAQUERYSETW UnicodeSet,IN SIZE_T BufferSize,OUT LPWSAQUERYSETW RelativeSet)771 WSABuildQuerySetBufferW(IN LPWSAQUERYSETW UnicodeSet,
772                         IN SIZE_T BufferSize,
773                         OUT LPWSAQUERYSETW RelativeSet)
774 {
775     INT ErrorCode = ERROR_SUCCESS;
776     SIZE_T SetSize;
777     WS_BUFFER Buffer;
778     LPWSAQUERYSETW NewSet;
779 
780     /* Find out how big the set really is */
781     SetSize = WSAComputeQuerySetSizeW(UnicodeSet);
782     if (SetSize <= BufferSize)
783     {
784         /* Configure the buffer */
785         Buffer.Position = (ULONG_PTR)RelativeSet;
786         Buffer.MaxSize = SetSize;
787         Buffer.BytesUsed = 0;
788 
789         /* Copy the set itself into the buffer */
790         NewSet = WsBufferAllocate(&Buffer, sizeof(*UnicodeSet), sizeof(PVOID));
791         *NewSet = *UnicodeSet;
792 
793         /* Now copy the data inside */
794         CopyQuerySetIndirectW(&Buffer, NewSet, UnicodeSet);
795     }
796     else
797     {
798         /* We failed */
799         ErrorCode = SOCKET_ERROR;
800     }
801 
802     /* Return to caller */
803     return ErrorCode;
804 }
805 
806 INT
807 WSAAPI
MapAnsiQuerySetToUnicode(IN LPWSAQUERYSETA AnsiSet,IN OUT PSIZE_T SetSize,OUT LPWSAQUERYSETW UnicodeSet)808 MapAnsiQuerySetToUnicode(IN LPWSAQUERYSETA AnsiSet,
809                          IN OUT PSIZE_T SetSize,
810                          OUT LPWSAQUERYSETW UnicodeSet)
811 {
812     INT ErrorCode = ERROR_SUCCESS;
813     SIZE_T AnsiSize, UnicodeSize;
814     LPWSAQUERYSETA AnsiCopy = NULL;
815     LPWSAQUERYSETW UnicodeCopy;
816     LPWSTR ServiceCopy = NULL, CommentCopy = NULL;
817     LPWSTR ContextCopy = NULL, QueryCopy = NULL;
818 
819     /* Calculate the size of the Ansi version and allocate space for a copy */
820     AnsiSize = WSAComputeQuerySetSizeA(AnsiSet);
821     AnsiCopy = HeapAlloc(WsSockHeap, 0, AnsiSize);
822     if (!AnsiCopy)
823     {
824         /* Fail, couldn't allocate memory */
825         ErrorCode = WSA_NOT_ENOUGH_MEMORY;
826         goto Exit;
827     }
828 
829     /* Build the relative buffer version */
830     ErrorCode = WSABuildQuerySetBufferA(AnsiSet, AnsiSize, AnsiCopy);
831     if (ErrorCode != ERROR_SUCCESS) goto Exit;
832 
833     /* Re-use the ANSI version since the fields match */
834     UnicodeCopy = (LPWSAQUERYSETW)AnsiCopy;
835 
836     /* Check if we have a service instance name */
837     if (AnsiCopy->lpszServiceInstanceName)
838     {
839         /* Duplicate it into unicode form */
840         ServiceCopy = UnicodeDupFromAnsi(AnsiCopy->lpszServiceInstanceName);
841         if (!ServiceCopy)
842         {
843             /* Fail */
844             ErrorCode = WSA_NOT_ENOUGH_MEMORY;
845             goto Exit;
846         }
847 
848         /* Set the new string pointer */
849         UnicodeCopy->lpszServiceInstanceName = ServiceCopy;
850     }
851 
852     /* Check if we have a service instance name */
853     if (AnsiCopy->lpszContext)
854     {
855         /* Duplicate it into unicode form */
856         ContextCopy = UnicodeDupFromAnsi(AnsiCopy->lpszContext);
857         if (!ContextCopy)
858         {
859             /* Fail */
860             ErrorCode = WSA_NOT_ENOUGH_MEMORY;
861             goto Exit;
862         }
863 
864         /* Set the new string pointer */
865         UnicodeCopy->lpszContext = ContextCopy;
866     }
867 
868     /* Check if we have a service instance name */
869     if (AnsiCopy->lpszComment)
870     {
871         /* Duplicate it into unicode form */
872         CommentCopy = UnicodeDupFromAnsi(AnsiCopy->lpszComment);
873         if (!CommentCopy)
874         {
875             /* Fail */
876             ErrorCode = WSA_NOT_ENOUGH_MEMORY;
877             goto Exit;
878         }
879 
880         /* Set the new string pointer */
881         UnicodeCopy->lpszComment = CommentCopy;
882     }
883 
884     /* Check if we have a query name */
885     if (AnsiCopy->lpszQueryString)
886     {
887         /* Duplicate it into unicode form */
888         QueryCopy = UnicodeDupFromAnsi(AnsiCopy->lpszQueryString);
889         if (!QueryCopy)
890         {
891             /* Fail */
892             ErrorCode = WSA_NOT_ENOUGH_MEMORY;
893             goto Exit;
894         }
895 
896         /* Set the new string pointer */
897         UnicodeCopy->lpszQueryString = QueryCopy;
898     }
899 
900     /* Now that we have the absolute unicode buffer, calculate its size */
901     UnicodeSize = WSAComputeQuerySetSizeW(UnicodeCopy);
902     if (UnicodeSize > *SetSize)
903     {
904         /* The buffer wasn't large enough; return how much we need */
905         *SetSize = UnicodeSize;
906         ErrorCode = WSAEFAULT;
907         goto Exit;
908     }
909 
910     /* Build the relative unicode buffer */
911     ErrorCode = WSABuildQuerySetBufferW(UnicodeCopy, *SetSize, UnicodeSet);
912 
913 Exit:
914     /* Free the Ansi copy if we had one */
915     if (AnsiCopy) HeapFree(WsSockHeap, 0, AnsiCopy);
916 
917     /* Free all the strings */
918     if (ServiceCopy) HeapFree(WsSockHeap, 0, ServiceCopy);
919     if (CommentCopy) HeapFree(WsSockHeap, 0, CommentCopy);
920     if (ContextCopy) HeapFree(WsSockHeap, 0, ContextCopy);
921     if (QueryCopy) HeapFree(WsSockHeap, 0, QueryCopy);
922 
923     /* Return error code */
924     return ErrorCode;
925 }
926 
927 INT
928 WSAAPI
MapUnicodeQuerySetToAnsi(IN LPWSAQUERYSETW UnicodeSet,IN OUT PSIZE_T SetSize,OUT LPWSAQUERYSETA AnsiSet)929 MapUnicodeQuerySetToAnsi(IN LPWSAQUERYSETW UnicodeSet,
930                          IN OUT PSIZE_T SetSize,
931                          OUT LPWSAQUERYSETA AnsiSet)
932 {
933     INT ErrorCode = ERROR_SUCCESS;
934     SIZE_T UnicodeSize, AnsiSize;
935     LPWSAQUERYSETW UnicodeCopy = NULL;
936     LPWSAQUERYSETA AnsiCopy;
937     LPSTR ServiceCopy = NULL, CommentCopy = NULL;
938     LPSTR ContextCopy = NULL, QueryCopy = NULL;
939 
940     /* Calculate the size of the Ansi version and allocate space for a copy */
941     UnicodeSize = WSAComputeQuerySetSizeW(UnicodeSet);
942     UnicodeCopy = HeapAlloc(WsSockHeap, 0, UnicodeSize);
943     if (!UnicodeCopy)
944     {
945         /* Fail, couldn't allocate memory */
946         ErrorCode = WSA_NOT_ENOUGH_MEMORY;
947         goto Exit;
948     }
949 
950     /* Build the relative buffer version */
951     ErrorCode = WSABuildQuerySetBufferW(UnicodeSet, UnicodeSize, UnicodeCopy);
952     if (ErrorCode != ERROR_SUCCESS) goto Exit;
953 
954     /* Re-use the Unicode version since the fields match */
955     AnsiCopy = (LPWSAQUERYSETA)UnicodeCopy;
956 
957     /* Check if we have a service instance name */
958     if (UnicodeCopy->lpszServiceInstanceName)
959     {
960         /* Duplicate it into unicode form */
961         ServiceCopy = AnsiDupFromUnicode(UnicodeCopy->lpszServiceInstanceName);
962         if (!ServiceCopy)
963         {
964             /* Fail */
965             ErrorCode = WSA_NOT_ENOUGH_MEMORY;
966             goto Exit;
967         }
968 
969         /* Set the new string pointer */
970         AnsiCopy->lpszServiceInstanceName = ServiceCopy;
971     }
972 
973     /* Check if we have a service instance name */
974     if (UnicodeCopy->lpszContext)
975     {
976         /* Duplicate it into unicode form */
977         ContextCopy = AnsiDupFromUnicode(UnicodeCopy->lpszContext);
978         if (!ContextCopy)
979         {
980             /* Fail */
981             ErrorCode = WSA_NOT_ENOUGH_MEMORY;
982             goto Exit;
983         }
984 
985         /* Set the new string pointer */
986         AnsiCopy->lpszContext = ContextCopy;
987     }
988 
989     /* Check if we have a service instance name */
990     if (UnicodeCopy->lpszComment)
991     {
992         /* Duplicate it into unicode form */
993         CommentCopy = AnsiDupFromUnicode(UnicodeCopy->lpszComment);
994         if (!CommentCopy)
995         {
996             /* Fail */
997             ErrorCode = WSA_NOT_ENOUGH_MEMORY;
998             goto Exit;
999         }
1000 
1001         /* Set the new string pointer */
1002         AnsiCopy->lpszComment = CommentCopy;
1003     }
1004 
1005     /* Check if we have a query name */
1006     if (UnicodeCopy->lpszQueryString)
1007     {
1008         /* Duplicate it into unicode form */
1009         QueryCopy = AnsiDupFromUnicode(UnicodeCopy->lpszQueryString);
1010         if (!QueryCopy)
1011         {
1012             /* Fail */
1013             ErrorCode = WSA_NOT_ENOUGH_MEMORY;
1014             goto Exit;
1015         }
1016 
1017         /* Set the new string pointer */
1018         AnsiCopy->lpszQueryString = QueryCopy;
1019     }
1020 
1021     /* Now that we have the absolute unicode buffer, calculate its size */
1022     AnsiSize = WSAComputeQuerySetSizeA(AnsiCopy);
1023     if (AnsiSize > *SetSize)
1024     {
1025         /* The buffer wasn't large enough; return how much we need */
1026         *SetSize = AnsiSize;
1027         ErrorCode = WSAEFAULT;
1028         goto Exit;
1029     }
1030 
1031     /* Build the relative unicode buffer */
1032     ErrorCode = WSABuildQuerySetBufferA(AnsiCopy, *SetSize, AnsiSet);
1033 
1034 Exit:
1035     /* Free the Ansi copy if we had one */
1036     if (UnicodeCopy) HeapFree(WsSockHeap, 0, UnicodeCopy);
1037 
1038     /* Free all the strings */
1039     if (ServiceCopy) HeapFree(WsSockHeap, 0, ServiceCopy);
1040     if (CommentCopy) HeapFree(WsSockHeap, 0, CommentCopy);
1041     if (ContextCopy) HeapFree(WsSockHeap, 0, ContextCopy);
1042     if (QueryCopy) HeapFree(WsSockHeap, 0, QueryCopy);
1043 
1044     /* Return error code */
1045     return ErrorCode;
1046 }
1047 
1048 INT
1049 WSAAPI
CopyQuerySetW(IN LPWSAQUERYSETW UnicodeSet,OUT LPWSAQUERYSETW * UnicodeCopy)1050 CopyQuerySetW(IN LPWSAQUERYSETW UnicodeSet,
1051               OUT LPWSAQUERYSETW *UnicodeCopy)
1052 {
1053     SIZE_T SetSize;
1054 
1055     /* Get the size */
1056     SetSize = WSAComputeQuerySetSizeW(UnicodeSet);
1057 
1058     /* Allocate memory for copy */
1059     *UnicodeCopy = HeapAlloc(WsSockHeap, 0, SetSize);
1060     if (!(*UnicodeCopy)) return WSA_NOT_ENOUGH_MEMORY;
1061 
1062     /* Build a copy and return */
1063     return WSABuildQuerySetBufferW(UnicodeSet, SetSize, *UnicodeCopy);
1064 }
1065