/****************************************************************************** * 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; }
/****************************************************************************** * 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); }
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; }
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; }
/****************************************************************************** * 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); }