void * UnicodeGetAllocBytesInternal(ConstUnicode ustr, // IN StringEncoding encoding, // IN ssize_t lengthInBytes, // IN size_t *retLength) // OUT: optional { const char *utf8Str = ustr; char *result = NULL; ASSERT(ustr != NULL); encoding = Unicode_ResolveEncoding(encoding); if (lengthInBytes == -1) { lengthInBytes = Unicode_LengthInBytes(ustr, STRING_ENCODING_UTF8); } switch (encoding) { case STRING_ENCODING_US_ASCII: if (!UnicodeSanityCheck(utf8Str, lengthInBytes, encoding)) { break; } // fall through case STRING_ENCODING_UTF8: result = Util_SafeMalloc(lengthInBytes + 1); memcpy(result, utf8Str, lengthInBytes + 1); if (retLength != NULL) { *retLength = lengthInBytes; } break; case STRING_ENCODING_UTF16_LE: if (!CodeSet_Utf8ToUtf16le(utf8Str, lengthInBytes, &result, retLength)) { // input should be valid UTF-8, no conversion error possible ASSERT_MEM_ALLOC(FALSE); } break; default: if (!CodeSet_GenericToGeneric("UTF-8", utf8Str, lengthInBytes, Unicode_EncodingEnumToName(encoding), CSGTG_NORMAL, &result, retLength)) { // XXX can't distinguish error cause ASSERT(result == NULL); } } return result; }
char * Unicode_EscapeBuffer(const void *buffer, // IN ssize_t lengthInBytes, // IN StringEncoding encoding) // IN { encoding = Unicode_ResolveEncoding(encoding); if (lengthInBytes == -1) { lengthInBytes = Unicode_LengthInBytes(buffer, encoding); } /* * The buffer could have NULs or 8-bit values inside. Escape it. */ return Escape_DoString("\\x", NonPrintableBytesToEscape, buffer, lengthInBytes, NULL); }
Unicode Unicode_AllocWithLength(const void *buffer, // IN: ssize_t lengthInBytes, // IN: StringEncoding encoding) // IN: { Unicode result; ASSERT(lengthInBytes >= 0 || lengthInBytes == -1); if (buffer == NULL) { ASSERT(lengthInBytes <= 0); return NULL; } encoding = Unicode_ResolveEncoding(encoding); if (lengthInBytes == -1) { lengthInBytes = Unicode_LengthInBytes(buffer, encoding); } result = UnicodeAllocInternal(buffer, lengthInBytes, encoding, FALSE); if (result == NULL) { char *escapedBuffer = Unicode_EscapeBuffer(buffer, lengthInBytes, encoding); /* * Log and panic on failure. */ Log("%s: Couldn't convert invalid buffer [%s] from %s to Unicode.\n", __FUNCTION__, escapedBuffer ? escapedBuffer : "(couldn't escape bytes)", Unicode_EncodingEnumToName(encoding)); free(escapedBuffer); PANIC(); } return result; }
Bool Unicode_IsBufferValid(const void *buffer, // IN ssize_t lengthInBytes, // IN StringEncoding encoding) // IN { if (buffer == NULL) { ASSERT(lengthInBytes <= 0); return TRUE; } encoding = Unicode_ResolveEncoding(encoding); if (encoding == STRING_ENCODING_US_ASCII) { return UnicodeSanityCheck(buffer, lengthInBytes, encoding); } if (lengthInBytes == -1) { lengthInBytes = Unicode_LengthInBytes(buffer, encoding); } return CodeSet_Validate(buffer, lengthInBytes, Unicode_EncodingEnumToName(encoding)); }
LONG Win32U_RegQueryValueEx(HKEY keyName, // IN: LPCSTR valueName, // IN: can be NULL LPDWORD reserved, // IN: reserved LPDWORD type, // OUT: can be NULL LPBYTE data, // OUT: can be NULL LPDWORD dataSize) // IN/OUT: can be NULL if data is NULL { LONG ret; utf16_t *valueNameW = Unicode_GetAllocUTF16(valueName); DWORD valueType; char *dataTemp = NULL; DWORD dataSizeTemp = 0; ASSERT(reserved == NULL); if (data) { ASSERT(dataSize != NULL); dataSizeTemp = *dataSize * 2; /* * We always allocate one extra word of space, so that we can write a * null character to the end of the data returned from the registry. * This protects us from crashing in the Win32UWriteBackRegData function * if the caller is attempting to get a value of type REG_SZ, and the * data is the registry is not properly null terminated. */ dataTemp = Util_SafeMalloc(dataSizeTemp + sizeof L'\0'); } ret = RegQueryValueExW(keyName, valueNameW, reserved, &valueType, dataTemp, &dataSizeTemp); if (dataTemp && ERROR_SUCCESS == ret && REG_SZ == valueType) { /* * Append a null word to the returned data, in case the value is not * null terminated in the registry. */ *((PWCHAR) (dataTemp + dataSizeTemp)) = L'\0'; /* * Get the length of the string. The registry doesn't enforce any rules * on the consistency of the data written into a value of REG_SZ type, * so a poorly written application can end up writing bytes _after_ the * NULL character in the string (e.g., because of an off-by-one error). * * If we try to convert those extra bytes to utf8, the conversion will * typically fail and we get a Panic() (cf. bug 352057). Getting the * string length here prevents us from crashing in this (fairly common) * case, and cuts down on the number of support calls. */ dataSizeTemp = Unicode_LengthInBytes(dataTemp, STRING_ENCODING_UTF16); } ret = Win32UWriteBackRegData(dataTemp, dataSizeTemp, data, dataSize, valueType, ret); /* Write back the type information if asked for */ if (type) { *type = valueType; } free(valueNameW); free(dataTemp); return ret; }