Пример #1
0
/******************************************************************************
 *             SysReAllocStringLen   [OLEAUT32.5]
 *
 * Change the length of a previously created BSTR.
 *
 * PARAMS
 *  old [O] BSTR to change the length of
 *  str [I] New source for pbstr
 *  len [I] Length of oleStr in wide characters
 *
 * RETURNS
 *  Success: 1. The size of pbstr is updated.
 *  Failure: 0, if len >= 0x80000000 or memory allocation fails.
 *
 * NOTES
 *  See BSTR(), SysAllocStringByteLen().
 *  *old may be changed by this function.
 */
int WINAPI SysReAllocStringLen(BSTR* old, const OLECHAR* str, unsigned int len)
{
    /* Detect integer overflow. */
    if (len >= ((UINT_MAX-sizeof(WCHAR)-sizeof(DWORD))/sizeof(WCHAR)))
	return 0;

    if (*old!=NULL) {
      BSTR old_copy = *old;
      DWORD newbytelen = len*sizeof(WCHAR);
      bstr_t *bstr = HeapReAlloc(GetProcessHeap(),0,((DWORD*)*old)-1,bstr_alloc_size(newbytelen));
      *old = bstr->u.str;
      bstr->size = newbytelen;
      /* Subtle hidden feature: The old string data is still there
       * when 'in' is NULL!
       * Some Microsoft program needs it.
       * FIXME: Is it a sideeffect of BSTR caching?
       */
      if (str && old_copy!=str) memmove(*old, str, newbytelen);
      (*old)[len] = 0;
    } else {
      /*
       * Allocate the new string
       */
      *old = SysAllocStringLen(str, len);
    }

    return 1;
}
Пример #2
0
/******************************************************************************
 *		SysFreeString	[OLEAUT32.6]
 *
 * Free a BSTR.
 *
 * PARAMS
 *  str [I] BSTR to free.
 *
 * RETURNS
 *  Nothing.
 *
 * NOTES
 *  See BSTR.
 *  str may be NULL, in which case this function does nothing.
 */
void WINAPI SysFreeString(BSTR str)
{
    bstr_cache_entry_t *cache_entry;
    bstr_t *bstr;

    if(!str)
        return;

    bstr = bstr_from_str(str);
    cache_entry = get_cache_entry(bstr->size+sizeof(WCHAR));
    if(cache_entry) {
        EnterCriticalSection(&cs_bstr_cache);

        if(cache_entry->cnt < sizeof(cache_entry->buf)/sizeof(*cache_entry->buf)) {
            cache_entry->buf[(cache_entry->head+cache_entry->cnt)%((sizeof(cache_entry->buf)/sizeof(*cache_entry->buf)))] = bstr;
            cache_entry->cnt++;

            if(WARN_ON(heap)) {
                unsigned i, n = bstr_alloc_size(bstr->size) / sizeof(DWORD) - 1;
                bstr->size = ARENA_FREE_FILLER;
                for(i=0; i<n; i++)
                    bstr->u.dwptr[i] = ARENA_FREE_FILLER;
            }

            LeaveCriticalSection(&cs_bstr_cache);
            return;
        }

        LeaveCriticalSection(&cs_bstr_cache);
    }

    HeapFree(GetProcessHeap(), 0, bstr);
}
Пример #3
0
static bstr_t *alloc_bstr(size_t size)
{
    bstr_cache_entry_t *cache_entry = get_cache_entry(size+sizeof(WCHAR));
    bstr_t *ret;

    if(cache_entry) {
        EnterCriticalSection(&cs_bstr_cache);

        if(!cache_entry->cnt) {
            cache_entry = get_cache_entry(size+sizeof(WCHAR)+BUCKET_SIZE);
            if(cache_entry && !cache_entry->cnt)
                cache_entry = NULL;
        }

        if(cache_entry) {
            ret = cache_entry->buf[cache_entry->head++];
            cache_entry->head %= sizeof(cache_entry->buf)/sizeof(*cache_entry->buf);
            cache_entry->cnt--;
        }

        LeaveCriticalSection(&cs_bstr_cache);

        if(cache_entry) {
            if(WARN_ON(heap)) {
                size_t tail;

                memset(ret, ARENA_INUSE_FILLER, FIELD_OFFSET(bstr_t, u.ptr[size+sizeof(WCHAR)]));
                tail = bstr_alloc_size(size) - FIELD_OFFSET(bstr_t, u.ptr[size+sizeof(WCHAR)]);
                if(tail)
                    memset(ret->u.ptr+size+sizeof(WCHAR), ARENA_TAIL_FILLER, tail);
            }
            ret->size = size;
            return ret;
        }
    }

    ret = HeapAlloc(GetProcessHeap(), 0, bstr_alloc_size(size));
    if(ret)
        ret->size = size;
    return ret;
}
Пример #4
0
static bstr_t *alloc_bstr(size_t size)
{
    bstr_cache_entry_t *cache_entry = get_cache_entry(size);
    bstr_t *ret;

    if(cache_entry) {
        EnterCriticalSection(&cs_bstr_cache);

        if(!cache_entry->cnt) {
            cache_entry = get_cache_entry(size+BUCKET_SIZE);
            if(cache_entry && !cache_entry->cnt)
                cache_entry = NULL;
        }

        if(cache_entry) {
            ret = cache_entry->buf[cache_entry->head++];
            cache_entry->head %= BUCKET_BUFFER_SIZE;
            cache_entry->cnt--;
        }

        LeaveCriticalSection(&cs_bstr_cache);

        if(cache_entry) {
            if(WARN_ON(heap)) {
                size_t fill_size = (FIELD_OFFSET(bstr_t, u.ptr[size])+2*sizeof(WCHAR)-1) & ~(sizeof(WCHAR)-1);
                memset(ret, ARENA_INUSE_FILLER, fill_size);
                memset((char *)ret+fill_size, ARENA_TAIL_FILLER, bstr_alloc_size(size)-fill_size);
            }
            ret->size = size;
            return ret;
        }
    }

    ret = HeapAlloc(GetProcessHeap(), 0, bstr_alloc_size(size));
    if(ret)
        ret->size = size;
    return ret;
}
Пример #5
0
/******************************************************************************
 *		SysFreeString	[OLEAUT32.6]
 *
 * Free a BSTR.
 *
 * PARAMS
 *  str [I] BSTR to free.
 *
 * RETURNS
 *  Nothing.
 *
 * NOTES
 *  See BSTR.
 *  str may be NULL, in which case this function does nothing.
 */
void WINAPI SysFreeString(BSTR str)
{
    bstr_cache_entry_t *cache_entry;
    bstr_t *bstr;

    if(!str)
        return;

    bstr = bstr_from_str(str);
    cache_entry = get_cache_entry(bstr->size+sizeof(WCHAR));
    if(cache_entry) {
        unsigned i;

        EnterCriticalSection(&cs_bstr_cache);

        /* According to tests, freeing a string that's already in cache doesn't corrupt anything.
         * For that to work we need to search the cache. */
        for(i=0; i < cache_entry->cnt; i++) {
            if(cache_entry->buf[(cache_entry->head+i) % BUCKET_BUFFER_SIZE] == bstr) {
                WARN_(heap)("String already is in cache!\n");
                LeaveCriticalSection(&cs_bstr_cache);
                return;
            }
        }

        if(cache_entry->cnt < sizeof(cache_entry->buf)/sizeof(*cache_entry->buf)) {
            cache_entry->buf[(cache_entry->head+cache_entry->cnt) % BUCKET_BUFFER_SIZE] = bstr;
            cache_entry->cnt++;

            if(WARN_ON(heap)) {
                unsigned n = bstr_alloc_size(bstr->size) / sizeof(DWORD) - 1;
                bstr->size = ARENA_FREE_FILLER;
                for(i=0; i<n; i++)
                    bstr->u.dwptr[i] = ARENA_FREE_FILLER;
            }

            LeaveCriticalSection(&cs_bstr_cache);
            return;
        }

        LeaveCriticalSection(&cs_bstr_cache);
    }

    HeapFree(GetProcessHeap(), 0, bstr);
}