/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS WinSock 2 API * FILE: dll/win32/ws2_32/src/qshelpr.c * PURPOSE: Query Set Conversion/Packing Helpers * PROGRAMMER: Alex Ionescu (alex@relsoft.net) */ /* INCLUDES ******************************************************************/ #include #define NDEBUG #include /* FUNCTIONS *****************************************************************/ LPSTR WSAAPI AnsiDupFromUnicode(IN LPCWSTR UnicodeString) { INT Length = 0; BOOL GoOn = TRUE; LPSTR DuplicatedString = NULL; INT ReturnValue; /* Start a loop (which should only run twice) */ while (GoOn) { /* Call the conversion function */ ReturnValue = WideCharToMultiByte(CP_ACP, 0, UnicodeString, -1, DuplicatedString, Length, NULL, NULL); if (ReturnValue > Length) { /* This is the first loop, and we have the real size now */ Length = ReturnValue; /* Allocate buffer for it */ DuplicatedString = HeapAlloc(WsSockHeap, 0, Length); if (!DuplicatedString) GoOn = FALSE; } else if (ReturnValue > 0) { /* The second loop was successful and we have the string */ GoOn = FALSE; } else { /* Some weird error happened */ if (DuplicatedString) HeapFree(WsSockHeap, 0, DuplicatedString); DuplicatedString = NULL; GoOn = FALSE; } } /* Return the duplicate */ return DuplicatedString; } LPWSTR WSAAPI UnicodeDupFromAnsi(IN LPCSTR AnsiString) { INT Length = 0; BOOL GoOn = TRUE; LPWSTR DuplicatedString = NULL; INT ReturnValue; /* Start a loop (which should only run twice) */ while (GoOn) { /* Call the conversion function */ ReturnValue = MultiByteToWideChar(CP_ACP, 0, AnsiString, -1, DuplicatedString, Length); if (ReturnValue > Length) { /* This is the first loop, and we have the real size now */ Length = ReturnValue; /* Allocate buffer for it */ DuplicatedString = HeapAlloc(WsSockHeap, 0, Length * sizeof(WCHAR)); if (!DuplicatedString) GoOn = FALSE; } else if (ReturnValue > 0) { /* The second loop was successful and we have the string */ GoOn = FALSE; } else { /* Some weird error happened */ if (DuplicatedString) HeapFree(WsSockHeap, 0, DuplicatedString); DuplicatedString = NULL; GoOn = FALSE; } } /* Return the duplicate */ return DuplicatedString; } SIZE_T WSAAPI ComputeStringSize(IN LPSTR String, IN BOOLEAN IsUnicode) { /* Return the size of the string, in bytes, including null-char */ return (IsUnicode) ? (wcslen((LPWSTR)String) + 1 ) * sizeof(WCHAR) : strlen(String) + sizeof(CHAR); } SIZE_T WSAAPI ComputeQuerySetSize(IN LPWSAQUERYSETA AnsiSet, IN BOOLEAN IsUnicode) { SIZE_T Size = sizeof(WSAQUERYSETA); //LPWSAQUERYSETW UnicodeSet = (LPWSAQUERYSETW)AnsiSet; DWORD i; /* Check for instance name */ if (AnsiSet->lpszServiceInstanceName) { /* Add its size */ Size += ComputeStringSize(AnsiSet->lpszServiceInstanceName, IsUnicode); } /* Check for Service Class ID */ if (AnsiSet->lpServiceClassId) { /* Align the current size and add GUID size */ Size = (Size + 3) & ~3; Size += sizeof(GUID); } /* Check for version data */ if (AnsiSet->lpVersion) { /* Align the current size and add GUID size */ Size = (Size + 3) & ~3; Size += sizeof(WSAVERSION); } /* Check for comment */ if (AnsiSet->lpszComment) { /* Align the current size and add string size */ Size = (Size + 1) & ~1; Size += ComputeStringSize(AnsiSet->lpszComment, IsUnicode); } /* Check for Provider ID */ if (AnsiSet->lpNSProviderId) { /* Align the current size and add GUID size */ Size = (Size + 3) & ~3; Size += sizeof(GUID); } /* Check for context */ if (AnsiSet->lpszContext) { /* Align the current size and add string size */ Size = (Size + 1) & ~1; Size += ComputeStringSize(AnsiSet->lpszContext, IsUnicode); } /* Check for query string */ if (AnsiSet->lpszQueryString) { /* Align the current size and add string size */ Size = (Size + 1) & ~1; Size += ComputeStringSize(AnsiSet->lpszQueryString, IsUnicode); } /* Check for AF Protocol data */ if (AnsiSet->lpafpProtocols) { /* Align the current size and add AFP size */ Size = (Size + 3) & ~3; Size += sizeof(AFPROTOCOLS) * AnsiSet->dwNumberOfProtocols; } /* Check for CSADDR buffer */ if (AnsiSet->lpcsaBuffer) { /* Align the current size */ Size = (Size + 3) & ~3; /* Loop all the addresses in the array */ for (i = 0; i < AnsiSet->dwNumberOfCsAddrs; i++) { /* Check for local sockaddr */ if (AnsiSet->lpcsaBuffer[i].LocalAddr.lpSockaddr) { /* Align the current size and add the sockaddr's length */ Size = (Size + 3) & ~3; Size += AnsiSet->lpcsaBuffer[i].LocalAddr.iSockaddrLength; } /* Check for remote sockaddr */ if (AnsiSet->lpcsaBuffer[i].RemoteAddr.lpSockaddr) { /* Align the current size and add the sockaddr's length */ Size = (Size + 3) & ~3; Size += AnsiSet->lpcsaBuffer[i].RemoteAddr.iSockaddrLength; } /* Add the sockaddr size itself */ Size += sizeof(CSADDR_INFO); } } /* Check for blob data */ if (AnsiSet->lpBlob) { /* Align the current size and add blob size */ Size = (Size + 3) & ~3; Size += sizeof(BLOB); /* Also add the actual blob data size, if it exists */ if (AnsiSet->lpBlob) Size += AnsiSet->lpBlob->cbSize; } /* Return the total size */ return Size; } SIZE_T WSAAPI WSAComputeQuerySetSizeA(IN LPWSAQUERYSETA AnsiSet) { /* Call the generic helper */ return ComputeQuerySetSize(AnsiSet, FALSE); } SIZE_T WSAAPI WSAComputeQuerySetSizeW(IN LPWSAQUERYSETW UnicodeSet) { /* Call the generic helper */ return ComputeQuerySetSize((LPWSAQUERYSETA)UnicodeSet, TRUE); } PVOID WSAAPI WsBufferAllocate(IN PWS_BUFFER Buffer, IN SIZE_T Size, IN DWORD Align) { PVOID NewPosition; /* Align the current usage */ Buffer->BytesUsed = (Buffer->BytesUsed + Align - 1) & ~(Align - 1); /* Update our location */ NewPosition = (PVOID)(Buffer->Position + Buffer->BytesUsed); /* Update the usage */ Buffer->BytesUsed += Size; /* Return new location */ return NewPosition; } VOID WSAAPI CopyBlobIndirect(IN PWS_BUFFER Buffer, IN OUT LPBLOB RelativeBlob, IN LPBLOB Blob) { /* Make sure we have blob data */ if ((Blob->pBlobData) && (Blob->cbSize)) { /* Allocate and copy the blob data */ RelativeBlob->pBlobData = WsBufferAllocate(Buffer, Blob->cbSize, sizeof(PVOID)); RtlCopyMemory(RelativeBlob->pBlobData, Blob->pBlobData, Blob->cbSize); } } VOID WSAAPI CopyAddrInfoArrayIndirect(IN PWS_BUFFER Buffer, IN OUT LPCSADDR_INFO RelativeCsaddr, IN DWORD Addresses, IN LPCSADDR_INFO Csaddr) { DWORD i; /* Loop for every address inside */ for (i = 0; i < Addresses; i++) { /* Check for a local address */ if ((Csaddr[i].LocalAddr.lpSockaddr) && (Csaddr[i].LocalAddr.iSockaddrLength)) { /* Allocate and copy the address */ RelativeCsaddr[i].LocalAddr.lpSockaddr = WsBufferAllocate(Buffer, Csaddr[i].LocalAddr.iSockaddrLength, sizeof(PVOID)); RtlCopyMemory(RelativeCsaddr[i].LocalAddr.lpSockaddr, Csaddr[i].LocalAddr.lpSockaddr, Csaddr[i].LocalAddr.iSockaddrLength); } else { /* Nothing in this address */ Csaddr[i].LocalAddr.lpSockaddr = NULL; Csaddr[i].LocalAddr.iSockaddrLength = 0; } /* Check for a remote address */ if ((Csaddr[i].RemoteAddr.lpSockaddr) && (Csaddr[i].RemoteAddr.iSockaddrLength)) { /* Allocate and copy the address */ RelativeCsaddr[i].RemoteAddr.lpSockaddr = WsBufferAllocate(Buffer, Csaddr[i].RemoteAddr.iSockaddrLength, sizeof(PVOID)); RtlCopyMemory(RelativeCsaddr[i].RemoteAddr.lpSockaddr, Csaddr[i].RemoteAddr.lpSockaddr, Csaddr[i].RemoteAddr.iSockaddrLength); } else { /* Nothing in this address */ Csaddr[i].RemoteAddr.lpSockaddr = NULL; Csaddr[i].RemoteAddr.iSockaddrLength = 0; } } } VOID WSAAPI CopyQuerySetIndirectA(IN PWS_BUFFER Buffer, IN OUT LPWSAQUERYSETA RelativeSet, IN LPWSAQUERYSETA AnsiSet) { LPSTR AnsiString; /* Get the service name */ AnsiString = AnsiSet->lpszServiceInstanceName; if (AnsiString) { /* One exists, allocate a space in the buffer for it */ RelativeSet->lpszServiceInstanceName = WsBufferAllocate(Buffer, strlen(AnsiString) + 1, sizeof(CHAR)); /* Copy it into the buffer */ strcpy(RelativeSet->lpszServiceInstanceName, AnsiString); } else { /* Nothing in the buffer */ RelativeSet->lpszServiceInstanceName = NULL; } /* Check for the service class ID */ if (AnsiSet->lpServiceClassId) { /* One exists, allocate a space in the buffer for it */ RelativeSet->lpServiceClassId = WsBufferAllocate(Buffer, sizeof(GUID), sizeof(PVOID)); /* Copy it into the buffer */ *(RelativeSet->lpServiceClassId) = *(AnsiSet->lpServiceClassId); } else { /* Nothing in the buffer */ RelativeSet->lpServiceClassId = NULL; } /* Get the version data */ if (AnsiSet->lpVersion) { /* One exists, allocate a space in the buffer for it */ RelativeSet->lpVersion = WsBufferAllocate(Buffer, sizeof(WSAVERSION), sizeof(PVOID)); /* Copy it into the buffer */ *(RelativeSet->lpVersion) = *(AnsiSet->lpVersion); } else { /* Nothing in the buffer */ RelativeSet->lpVersion = NULL; } /* Get the comment */ AnsiString = AnsiSet->lpszComment; if (AnsiString) { /* One exists, allocate a space in the buffer for it */ RelativeSet->lpszComment = WsBufferAllocate(Buffer, strlen(AnsiString) + 1, sizeof(CHAR)); /* Copy it into the buffer */ strcpy(RelativeSet->lpszComment, AnsiString); } else { /* Nothing in the buffer */ RelativeSet->lpszComment = NULL; } /* Get the NS Provider ID */ if (AnsiSet->lpNSProviderId) { /* One exists, allocate a space in the buffer for it */ RelativeSet->lpNSProviderId = WsBufferAllocate(Buffer, sizeof(GUID), sizeof(PVOID)); /* Copy it into the buffer */ *(RelativeSet->lpNSProviderId) = *(AnsiSet->lpNSProviderId); } else { /* Nothing in the buffer */ RelativeSet->lpNSProviderId = NULL; } /* Get the context */ AnsiString = AnsiSet->lpszContext; if (AnsiString) { /* One exists, allocate a space in the buffer for it */ RelativeSet->lpszContext = WsBufferAllocate(Buffer, strlen(AnsiString) + 1, sizeof(CHAR)); /* Copy it into the buffer */ strcpy(RelativeSet->lpszContext, AnsiString); } else { /* Nothing in the buffer */ RelativeSet->lpszContext = NULL; } /* Get the query string */ AnsiString = AnsiSet->lpszQueryString; if (AnsiString) { /* One exists, allocate a space in the buffer for it */ RelativeSet->lpszQueryString = WsBufferAllocate(Buffer, strlen(AnsiString) + 1, sizeof(CHAR)); /* Copy it into the buffer */ strcpy(RelativeSet->lpszQueryString, AnsiString); } else { /* Nothing in the buffer */ RelativeSet->lpszQueryString = NULL; } /* Check for a protocol structure with non-zero protocols */ if ((AnsiSet->lpafpProtocols) && (AnsiSet->dwNumberOfProtocols)) { /* One exists, allocate space for it */ RelativeSet->lpafpProtocols = WsBufferAllocate(Buffer, AnsiSet->dwNumberOfProtocols * sizeof(AFPROTOCOLS), sizeof(PVOID)); /* Copy it into the buffer */ RtlCopyMemory(RelativeSet->lpafpProtocols, AnsiSet->lpafpProtocols, AnsiSet->dwNumberOfProtocols * sizeof(AFPROTOCOLS)); } else { /* Nothing in the buffer */ RelativeSet->lpafpProtocols = NULL; RelativeSet->dwNumberOfProtocols = 0; } /* Check if we have a CSADDR with addresses inside */ if ((AnsiSet->lpcsaBuffer) && (AnsiSet->dwNumberOfCsAddrs)) { /* Allocate and copy the CSADDR structure itself */ RelativeSet->lpcsaBuffer = WsBufferAllocate(Buffer, AnsiSet->dwNumberOfCsAddrs * sizeof(CSADDR_INFO), sizeof(PVOID)); /* Copy it into the buffer */ RtlCopyMemory(RelativeSet->lpcsaBuffer, AnsiSet->lpcsaBuffer, AnsiSet->dwNumberOfCsAddrs * sizeof(CSADDR_INFO)); /* Copy the addresses inside the CSADDR */ CopyAddrInfoArrayIndirect(Buffer, RelativeSet->lpcsaBuffer, AnsiSet->dwNumberOfCsAddrs, AnsiSet->lpcsaBuffer); } else { /* Nothing in the buffer */ RelativeSet->lpcsaBuffer = NULL; RelativeSet->dwNumberOfCsAddrs = 0; } /* Check for blob data */ if (AnsiSet->lpBlob) { /* Allocate and copy the blob itself */ RelativeSet->lpBlob = WsBufferAllocate(Buffer, sizeof(BLOB), sizeof(PVOID)); *(RelativeSet->lpBlob) = *(AnsiSet->lpBlob); /* Copy the data inside the blob */ CopyBlobIndirect(Buffer, RelativeSet->lpBlob, AnsiSet->lpBlob); } else { /* Nothing in the buffer */ RelativeSet->lpBlob = NULL; } } VOID WSAAPI CopyQuerySetIndirectW(IN PWS_BUFFER Buffer, IN OUT LPWSAQUERYSETW RelativeSet, IN LPWSAQUERYSETW UnicodeSet) { LPWSTR UnicodeString; /* Get the service name */ UnicodeString = UnicodeSet->lpszServiceInstanceName; if (UnicodeString) { /* One exists, allocate a space in the buffer for it */ RelativeSet->lpszServiceInstanceName = WsBufferAllocate(Buffer, (wcslen(UnicodeString) + 1) * sizeof(WCHAR), sizeof(CHAR)); /* Copy it into the buffer */ wcscpy(RelativeSet->lpszServiceInstanceName, UnicodeString); } else { /* Nothing in the buffer */ RelativeSet->lpszServiceInstanceName = NULL; } /* Check for the service class ID */ if (UnicodeSet->lpServiceClassId) { /* One exists, allocate a space in the buffer for it */ RelativeSet->lpServiceClassId = WsBufferAllocate(Buffer, sizeof(GUID), sizeof(PVOID)); /* Copy it into the buffer */ *(RelativeSet->lpServiceClassId) = *(UnicodeSet->lpServiceClassId); } else { /* Nothing in the buffer */ RelativeSet->lpServiceClassId = NULL; } /* Get the version data */ if (UnicodeSet->lpVersion) { /* One exists, allocate a space in the buffer for it */ RelativeSet->lpVersion = WsBufferAllocate(Buffer, sizeof(WSAVERSION), sizeof(PVOID)); /* Copy it into the buffer */ *(RelativeSet->lpVersion) = *(UnicodeSet->lpVersion); } else { /* Nothing in the buffer */ RelativeSet->lpVersion = NULL; } /* Get the comment */ UnicodeString = UnicodeSet->lpszComment; if (UnicodeString) { /* One exists, allocate a space in the buffer for it */ RelativeSet->lpszComment = WsBufferAllocate(Buffer, (wcslen(UnicodeString) + 1) * sizeof(WCHAR), sizeof(CHAR)); /* Copy it into the buffer */ wcscpy(RelativeSet->lpszComment, UnicodeString); } else { /* Nothing in the buffer */ RelativeSet->lpszComment = NULL; } /* Get the NS Provider ID */ if (UnicodeSet->lpNSProviderId) { /* One exists, allocate a space in the buffer for it */ RelativeSet->lpNSProviderId = WsBufferAllocate(Buffer, sizeof(GUID), sizeof(PVOID)); /* Copy it into the buffer */ *(RelativeSet->lpNSProviderId) = *(UnicodeSet->lpNSProviderId); } else { /* Nothing in the buffer */ RelativeSet->lpNSProviderId = NULL; } /* Get the context */ UnicodeString = UnicodeSet->lpszContext; if (UnicodeString) { /* One exists, allocate a space in the buffer for it */ RelativeSet->lpszContext = WsBufferAllocate(Buffer, (wcslen(UnicodeString) + 1) * sizeof(WCHAR), sizeof(CHAR)); /* Copy it into the buffer */ wcscpy(RelativeSet->lpszContext, UnicodeString); } else { /* Nothing in the buffer */ RelativeSet->lpszContext = NULL; } /* Get the query string */ UnicodeString = UnicodeSet->lpszQueryString; if (UnicodeString) { /* One exists, allocate a space in the buffer for it */ RelativeSet->lpszQueryString = WsBufferAllocate(Buffer, (wcslen(UnicodeString) + 1) * sizeof(WCHAR), sizeof(CHAR)); /* Copy it into the buffer */ wcscpy(RelativeSet->lpszQueryString, UnicodeString); } else { /* Nothing in the buffer */ RelativeSet->lpszQueryString = NULL; } /* Check for a protocol structure with non-zero protocols */ if ((UnicodeSet->lpafpProtocols) && (UnicodeSet->dwNumberOfProtocols)) { /* One exists, allocate space for it */ RelativeSet->lpafpProtocols = WsBufferAllocate(Buffer, UnicodeSet->dwNumberOfProtocols * sizeof(AFPROTOCOLS), sizeof(PVOID)); /* Copy it into the buffer */ RtlCopyMemory(RelativeSet->lpafpProtocols, UnicodeSet->lpafpProtocols, UnicodeSet->dwNumberOfProtocols * sizeof(AFPROTOCOLS)); } else { /* Nothing in the buffer */ RelativeSet->lpafpProtocols = NULL; RelativeSet->dwNumberOfProtocols = 0; } /* Check if we have a CSADDR with addresses inside */ if ((UnicodeSet->lpcsaBuffer) && (UnicodeSet->dwNumberOfCsAddrs)) { /* Allocate and copy the CSADDR structure itself */ RelativeSet->lpcsaBuffer = WsBufferAllocate(Buffer, UnicodeSet->dwNumberOfCsAddrs * sizeof(CSADDR_INFO), sizeof(PVOID)); /* Copy it into the buffer */ RtlCopyMemory(RelativeSet->lpcsaBuffer, UnicodeSet->lpcsaBuffer, UnicodeSet->dwNumberOfCsAddrs * sizeof(CSADDR_INFO)); /* Copy the addresses inside the CSADDR */ CopyAddrInfoArrayIndirect(Buffer, RelativeSet->lpcsaBuffer, UnicodeSet->dwNumberOfCsAddrs, UnicodeSet->lpcsaBuffer); } else { /* Nothing in the buffer */ RelativeSet->lpcsaBuffer = NULL; RelativeSet->dwNumberOfCsAddrs = 0; } /* Check for blob data */ if (UnicodeSet->lpBlob) { /* Allocate and copy the blob itself */ RelativeSet->lpBlob = WsBufferAllocate(Buffer, sizeof(BLOB), sizeof(PVOID)); *(RelativeSet->lpBlob) = *(UnicodeSet->lpBlob); /* Copy the data inside the blob */ CopyBlobIndirect(Buffer, RelativeSet->lpBlob, UnicodeSet->lpBlob); } else { /* Nothing in the buffer */ RelativeSet->lpBlob = NULL; } } INT WSAAPI WSABuildQuerySetBufferA(IN LPWSAQUERYSETA AnsiSet, IN SIZE_T BufferSize, OUT LPWSAQUERYSETA RelativeSet) { INT ErrorCode = ERROR_SUCCESS; SIZE_T SetSize; WS_BUFFER Buffer; LPWSAQUERYSETA NewSet; /* Find out how big the set really is */ SetSize = WSAComputeQuerySetSizeA(AnsiSet); if (SetSize <= BufferSize) { /* Configure the buffer */ Buffer.Position = (ULONG_PTR)RelativeSet; Buffer.MaxSize = SetSize; Buffer.BytesUsed = 0; /* Copy the set itself into the buffer */ NewSet = WsBufferAllocate(&Buffer, sizeof(*AnsiSet), sizeof(PVOID)); *NewSet = *AnsiSet; /* Now copy the data inside */ CopyQuerySetIndirectA(&Buffer, NewSet, AnsiSet); } else { /* We failed */ ErrorCode = SOCKET_ERROR; } /* Return to caller */ return ErrorCode; } INT WSAAPI WSABuildQuerySetBufferW(IN LPWSAQUERYSETW UnicodeSet, IN SIZE_T BufferSize, OUT LPWSAQUERYSETW RelativeSet) { INT ErrorCode = ERROR_SUCCESS; SIZE_T SetSize; WS_BUFFER Buffer; LPWSAQUERYSETW NewSet; /* Find out how big the set really is */ SetSize = WSAComputeQuerySetSizeW(UnicodeSet); if (SetSize <= BufferSize) { /* Configure the buffer */ Buffer.Position = (ULONG_PTR)RelativeSet; Buffer.MaxSize = SetSize; Buffer.BytesUsed = 0; /* Copy the set itself into the buffer */ NewSet = WsBufferAllocate(&Buffer, sizeof(*UnicodeSet), sizeof(PVOID)); *NewSet = *UnicodeSet; /* Now copy the data inside */ CopyQuerySetIndirectW(&Buffer, NewSet, UnicodeSet); } else { /* We failed */ ErrorCode = SOCKET_ERROR; } /* Return to caller */ return ErrorCode; } INT WSAAPI MapAnsiQuerySetToUnicode(IN LPWSAQUERYSETA AnsiSet, IN OUT PSIZE_T SetSize, OUT LPWSAQUERYSETW UnicodeSet) { INT ErrorCode = ERROR_SUCCESS; SIZE_T AnsiSize, UnicodeSize; LPWSAQUERYSETA AnsiCopy = NULL; LPWSAQUERYSETW UnicodeCopy; LPWSTR ServiceCopy = NULL, CommentCopy = NULL; LPWSTR ContextCopy = NULL, QueryCopy = NULL; /* Calculate the size of the Ansi version and allocate space for a copy */ AnsiSize = WSAComputeQuerySetSizeA(AnsiSet); AnsiCopy = HeapAlloc(WsSockHeap, 0, AnsiSize); if (!AnsiCopy) { /* Fail, couldn't allocate memory */ ErrorCode = WSA_NOT_ENOUGH_MEMORY; goto Exit; } /* Build the relative buffer version */ ErrorCode = WSABuildQuerySetBufferA(AnsiSet, AnsiSize, AnsiCopy); if (ErrorCode != ERROR_SUCCESS) goto Exit; /* Re-use the ANSI version since the fields match */ UnicodeCopy = (LPWSAQUERYSETW)AnsiCopy; /* Check if we have a service instance name */ if (AnsiCopy->lpszServiceInstanceName) { /* Duplicate it into unicode form */ ServiceCopy = UnicodeDupFromAnsi(AnsiCopy->lpszServiceInstanceName); if (!ServiceCopy) { /* Fail */ ErrorCode = WSA_NOT_ENOUGH_MEMORY; goto Exit; } /* Set the new string pointer */ UnicodeCopy->lpszServiceInstanceName = ServiceCopy; } /* Check if we have a service instance name */ if (AnsiCopy->lpszContext) { /* Duplicate it into unicode form */ ContextCopy = UnicodeDupFromAnsi(AnsiCopy->lpszContext); if (!ContextCopy) { /* Fail */ ErrorCode = WSA_NOT_ENOUGH_MEMORY; goto Exit; } /* Set the new string pointer */ UnicodeCopy->lpszContext = ContextCopy; } /* Check if we have a service instance name */ if (AnsiCopy->lpszComment) { /* Duplicate it into unicode form */ CommentCopy = UnicodeDupFromAnsi(AnsiCopy->lpszComment); if (!CommentCopy) { /* Fail */ ErrorCode = WSA_NOT_ENOUGH_MEMORY; goto Exit; } /* Set the new string pointer */ UnicodeCopy->lpszComment = CommentCopy; } /* Check if we have a query name */ if (AnsiCopy->lpszQueryString) { /* Duplicate it into unicode form */ QueryCopy = UnicodeDupFromAnsi(AnsiCopy->lpszQueryString); if (!QueryCopy) { /* Fail */ ErrorCode = WSA_NOT_ENOUGH_MEMORY; goto Exit; } /* Set the new string pointer */ UnicodeCopy->lpszQueryString = QueryCopy; } /* Now that we have the absolute unicode buffer, calculate its size */ UnicodeSize = WSAComputeQuerySetSizeW(UnicodeCopy); if (UnicodeSize > *SetSize) { /* The buffer wasn't large enough; return how much we need */ *SetSize = UnicodeSize; ErrorCode = WSAEFAULT; goto Exit; } /* Build the relative unicode buffer */ ErrorCode = WSABuildQuerySetBufferW(UnicodeCopy, *SetSize, UnicodeSet); Exit: /* Free the Ansi copy if we had one */ if (AnsiCopy) HeapFree(WsSockHeap, 0, AnsiCopy); /* Free all the strings */ if (ServiceCopy) HeapFree(WsSockHeap, 0, ServiceCopy); if (CommentCopy) HeapFree(WsSockHeap, 0, CommentCopy); if (ContextCopy) HeapFree(WsSockHeap, 0, ContextCopy); if (QueryCopy) HeapFree(WsSockHeap, 0, QueryCopy); /* Return error code */ return ErrorCode; } INT WSAAPI MapUnicodeQuerySetToAnsi(IN LPWSAQUERYSETW UnicodeSet, IN OUT PSIZE_T SetSize, OUT LPWSAQUERYSETA AnsiSet) { INT ErrorCode = ERROR_SUCCESS; SIZE_T UnicodeSize, AnsiSize; LPWSAQUERYSETW UnicodeCopy = NULL; LPWSAQUERYSETA AnsiCopy; LPSTR ServiceCopy = NULL, CommentCopy = NULL; LPSTR ContextCopy = NULL, QueryCopy = NULL; /* Calculate the size of the Ansi version and allocate space for a copy */ UnicodeSize = WSAComputeQuerySetSizeW(UnicodeSet); UnicodeCopy = HeapAlloc(WsSockHeap, 0, UnicodeSize); if (!UnicodeCopy) { /* Fail, couldn't allocate memory */ ErrorCode = WSA_NOT_ENOUGH_MEMORY; goto Exit; } /* Build the relative buffer version */ ErrorCode = WSABuildQuerySetBufferW(UnicodeSet, UnicodeSize, UnicodeCopy); if (ErrorCode != ERROR_SUCCESS) goto Exit; /* Re-use the Unicode version since the fields match */ AnsiCopy = (LPWSAQUERYSETA)UnicodeCopy; /* Check if we have a service instance name */ if (UnicodeCopy->lpszServiceInstanceName) { /* Duplicate it into unicode form */ ServiceCopy = AnsiDupFromUnicode(UnicodeCopy->lpszServiceInstanceName); if (!ServiceCopy) { /* Fail */ ErrorCode = WSA_NOT_ENOUGH_MEMORY; goto Exit; } /* Set the new string pointer */ AnsiCopy->lpszServiceInstanceName = ServiceCopy; } /* Check if we have a service instance name */ if (UnicodeCopy->lpszContext) { /* Duplicate it into unicode form */ ContextCopy = AnsiDupFromUnicode(UnicodeCopy->lpszContext); if (!ContextCopy) { /* Fail */ ErrorCode = WSA_NOT_ENOUGH_MEMORY; goto Exit; } /* Set the new string pointer */ AnsiCopy->lpszContext = ContextCopy; } /* Check if we have a service instance name */ if (UnicodeCopy->lpszComment) { /* Duplicate it into unicode form */ CommentCopy = AnsiDupFromUnicode(UnicodeCopy->lpszComment); if (!CommentCopy) { /* Fail */ ErrorCode = WSA_NOT_ENOUGH_MEMORY; goto Exit; } /* Set the new string pointer */ AnsiCopy->lpszComment = CommentCopy; } /* Check if we have a query name */ if (UnicodeCopy->lpszQueryString) { /* Duplicate it into unicode form */ QueryCopy = AnsiDupFromUnicode(UnicodeCopy->lpszQueryString); if (!QueryCopy) { /* Fail */ ErrorCode = WSA_NOT_ENOUGH_MEMORY; goto Exit; } /* Set the new string pointer */ AnsiCopy->lpszQueryString = QueryCopy; } /* Now that we have the absolute unicode buffer, calculate its size */ AnsiSize = WSAComputeQuerySetSizeA(AnsiCopy); if (AnsiSize > *SetSize) { /* The buffer wasn't large enough; return how much we need */ *SetSize = AnsiSize; ErrorCode = WSAEFAULT; goto Exit; } /* Build the relative unicode buffer */ ErrorCode = WSABuildQuerySetBufferA(AnsiCopy, *SetSize, AnsiSet); Exit: /* Free the Ansi copy if we had one */ if (UnicodeCopy) HeapFree(WsSockHeap, 0, UnicodeCopy); /* Free all the strings */ if (ServiceCopy) HeapFree(WsSockHeap, 0, ServiceCopy); if (CommentCopy) HeapFree(WsSockHeap, 0, CommentCopy); if (ContextCopy) HeapFree(WsSockHeap, 0, ContextCopy); if (QueryCopy) HeapFree(WsSockHeap, 0, QueryCopy); /* Return error code */ return ErrorCode; } INT WSAAPI CopyQuerySetW(IN LPWSAQUERYSETW UnicodeSet, OUT LPWSAQUERYSETW *UnicodeCopy) { SIZE_T SetSize; /* Get the size */ SetSize = WSAComputeQuerySetSizeW(UnicodeSet); /* Allocate memory for copy */ *UnicodeCopy = HeapAlloc(WsSockHeap, 0, SetSize); if (!(*UnicodeCopy)) return WSA_NOT_ENOUGH_MEMORY; /* Build a copy and return */ return WSABuildQuerySetBufferW(UnicodeSet, SetSize, *UnicodeCopy); }