[SCRRUN] Sync with Wine Staging 1.7.47. CORE-9924

svn path=/trunk/; revision=68498
This commit is contained in:
Amine Khaldi 2015-07-20 22:55:19 +00:00
parent 786aa41d34
commit b672c2d10d
5 changed files with 703 additions and 74 deletions

View file

@ -1,5 +1,6 @@
/*
* Copyright (C) 2012 Alistair Leslie-Hughes
* Copyright 2015 Nikolay Sivov for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -18,18 +19,347 @@
#include "scrrun_private.h"
#include <olectl.h>
#include <wine/list.h>
#include <wine/port.h>
#include <wine/unicode.h>
#define BUCKET_COUNT 509
#define DICT_HASH_MOD 1201
/* Implementation details
Dictionary contains one list that links all pairs, this way
order in which they were added is preserved. Each bucket has
its own list to hold all pairs in this bucket. Initially all
bucket lists are zeroed and we init them once we about to add
first pair.
When pair is removed it's unlinked from both lists; if it was
a last pair in a bucket list it stays empty in initialized state.
Preserving pair order is important for enumeration, so far testing
indicates that pairs are not reordered basing on hash value.
*/
struct keyitem_pair {
struct list entry;
struct list bucket;
DWORD hash;
VARIANT key;
VARIANT item;
};
typedef struct
{
IDictionary IDictionary_iface;
LONG ref;
CompareMethod method;
LONG count;
struct list pairs;
struct list buckets[BUCKET_COUNT];
struct list notifier;
} dictionary;
struct dictionary_enum {
IEnumVARIANT IEnumVARIANT_iface;
LONG ref;
dictionary *dict;
struct list *cur;
struct list notify;
};
static inline dictionary *impl_from_IDictionary(IDictionary *iface)
{
return CONTAINING_RECORD(iface, dictionary, IDictionary_iface);
}
static inline struct dictionary_enum *impl_from_IEnumVARIANT(IEnumVARIANT *iface)
{
return CONTAINING_RECORD(iface, struct dictionary_enum, IEnumVARIANT_iface);
}
static inline struct list *get_bucket_head(dictionary *dict, DWORD hash)
{
return &dict->buckets[hash % BUCKET_COUNT];
}
static inline BOOL is_string_key(const VARIANT *key)
{
return V_VT(key) == VT_BSTR || V_VT(key) == (VT_BSTR|VT_BYREF);
}
/* Only for VT_BSTR or VT_BSTR|VT_BYREF types */
static inline WCHAR *get_key_strptr(const VARIANT *key)
{
if (V_VT(key) == VT_BSTR)
return V_BSTR(key);
if (V_BSTRREF(key))
return *V_BSTRREF(key);
return NULL;
}
/* should be used only when both keys are of string type, it's not checked */
static inline int strcmp_key(const dictionary *dict, const VARIANT *key1, const VARIANT *key2)
{
const WCHAR *str1, *str2;
str1 = get_key_strptr(key1);
str2 = get_key_strptr(key2);
return dict->method == BinaryCompare ? strcmpW(str1, str2) : strcmpiW(str1, str2);
}
static BOOL is_matching_key(const dictionary *dict, const struct keyitem_pair *pair, const VARIANT *key, DWORD hash)
{
if (is_string_key(key) && is_string_key(&pair->key)) {
if (hash != pair->hash)
return FALSE;
return strcmp_key(dict, key, &pair->key) == 0;
}
if ((is_string_key(key) && !is_string_key(&pair->key)) ||
(!is_string_key(key) && is_string_key(&pair->key)))
return FALSE;
/* for numeric keys only check hash */
return hash == pair->hash;
}
static struct keyitem_pair *get_keyitem_pair(dictionary *dict, VARIANT *key)
{
struct keyitem_pair *pair;
struct list *head, *entry;
VARIANT hash;
HRESULT hr;
hr = IDictionary_get_HashVal(&dict->IDictionary_iface, key, &hash);
if (FAILED(hr))
return NULL;
head = get_bucket_head(dict, V_I4(&hash));
if (!head->next || list_empty(head))
return NULL;
entry = list_head(head);
do {
pair = LIST_ENTRY(entry, struct keyitem_pair, bucket);
if (is_matching_key(dict, pair, key, V_I4(&hash))) return pair;
} while ((entry = list_next(head, entry)));
return NULL;
}
static HRESULT add_keyitem_pair(dictionary *dict, VARIANT *key, VARIANT *item)
{
struct keyitem_pair *pair;
struct list *head;
VARIANT hash;
HRESULT hr;
hr = IDictionary_get_HashVal(&dict->IDictionary_iface, key, &hash);
if (FAILED(hr))
return hr;
pair = heap_alloc(sizeof(*pair));
if (!pair)
return E_OUTOFMEMORY;
pair->hash = V_I4(&hash);
VariantInit(&pair->key);
VariantInit(&pair->item);
hr = VariantCopyInd(&pair->key, key);
if (FAILED(hr))
goto failed;
hr = VariantCopyInd(&pair->item, item);
if (FAILED(hr))
goto failed;
head = get_bucket_head(dict, pair->hash);
if (!head->next)
/* this only happens once per bucket */
list_init(head);
/* link to bucket list and to full list */
list_add_tail(head, &pair->bucket);
list_add_tail(&dict->pairs, &pair->entry);
dict->count++;
return S_OK;
failed:
VariantClear(&pair->key);
VariantClear(&pair->item);
heap_free(pair);
return hr;
}
static void free_keyitem_pair(struct keyitem_pair *pair)
{
VariantClear(&pair->key);
VariantClear(&pair->item);
heap_free(pair);
}
static HRESULT WINAPI dict_enum_QueryInterface(IEnumVARIANT *iface, REFIID riid, void **obj)
{
struct dictionary_enum *This = impl_from_IEnumVARIANT(iface);
TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), obj);
if (IsEqualIID(riid, &IID_IEnumVARIANT) || IsEqualIID(riid, &IID_IUnknown)) {
*obj = iface;
IEnumVARIANT_AddRef(iface);
return S_OK;
}
else {
WARN("interface not supported %s\n", debugstr_guid(riid));
*obj = NULL;
return E_NOINTERFACE;
}
}
static ULONG WINAPI dict_enum_AddRef(IEnumVARIANT *iface)
{
struct dictionary_enum *This = impl_from_IEnumVARIANT(iface);
TRACE("(%p)\n", This);
return InterlockedIncrement(&This->ref);
}
static ULONG WINAPI dict_enum_Release(IEnumVARIANT *iface)
{
struct dictionary_enum *This = impl_from_IEnumVARIANT(iface);
LONG ref;
TRACE("(%p)\n", This);
ref = InterlockedDecrement(&This->ref);
if(ref == 0) {
list_remove(&This->notify);
IDictionary_Release(&This->dict->IDictionary_iface);
heap_free(This);
}
return ref;
}
static HRESULT WINAPI dict_enum_Next(IEnumVARIANT *iface, ULONG count, VARIANT *keys, ULONG *fetched)
{
struct dictionary_enum *This = impl_from_IEnumVARIANT(iface);
struct keyitem_pair *pair;
ULONG i = 0;
TRACE("(%p)->(%u %p %p)\n", This, count, keys, fetched);
if (fetched)
*fetched = 0;
if (!count)
return S_OK;
while (This->cur && i < count) {
pair = LIST_ENTRY(This->cur, struct keyitem_pair, entry);
VariantCopy(&keys[i], &pair->key);
This->cur = list_next(&This->dict->pairs, This->cur);
i++;
}
if (fetched)
*fetched = i;
return i < count ? S_FALSE : S_OK;
}
static HRESULT WINAPI dict_enum_Skip(IEnumVARIANT *iface, ULONG count)
{
struct dictionary_enum *This = impl_from_IEnumVARIANT(iface);
TRACE("(%p)->(%u)\n", This, count);
if (!count)
return S_OK;
if (!This->cur)
return S_FALSE;
while (count--) {
This->cur = list_next(&This->dict->pairs, This->cur);
if (!This->cur) break;
}
return count == 0 ? S_OK : S_FALSE;
}
static HRESULT WINAPI dict_enum_Reset(IEnumVARIANT *iface)
{
struct dictionary_enum *This = impl_from_IEnumVARIANT(iface);
TRACE("(%p)\n", This);
This->cur = list_head(&This->dict->pairs);
return S_OK;
}
static HRESULT create_dict_enum(dictionary*, IUnknown**);
static HRESULT WINAPI dict_enum_Clone(IEnumVARIANT *iface, IEnumVARIANT **cloned)
{
struct dictionary_enum *This = impl_from_IEnumVARIANT(iface);
TRACE("(%p)->(%p)\n", This, cloned);
return create_dict_enum(This->dict, (IUnknown**)cloned);
}
static const IEnumVARIANTVtbl dictenumvtbl = {
dict_enum_QueryInterface,
dict_enum_AddRef,
dict_enum_Release,
dict_enum_Next,
dict_enum_Skip,
dict_enum_Reset,
dict_enum_Clone
};
static HRESULT create_dict_enum(dictionary *dict, IUnknown **ret)
{
struct dictionary_enum *This;
*ret = NULL;
This = heap_alloc(sizeof(*This));
if (!This)
return E_OUTOFMEMORY;
This->IEnumVARIANT_iface.lpVtbl = &dictenumvtbl;
This->ref = 1;
This->cur = list_head(&dict->pairs);
list_add_tail(&dict->notifier, &This->notify);
This->dict = dict;
IDictionary_AddRef(&dict->IDictionary_iface);
*ret = (IUnknown*)&This->IEnumVARIANT_iface;
return S_OK;
}
static void notify_remove_pair(struct list *notifier, struct list *pair)
{
struct dictionary_enum *dict_enum;
struct list *cur;
LIST_FOR_EACH(cur, notifier) {
dict_enum = LIST_ENTRY(cur, struct dictionary_enum, notify);
if (!pair)
dict_enum->cur = list_head(&dict_enum->dict->pairs);
else if (dict_enum->cur == pair) {
dict_enum->cur = list_next(&dict_enum->dict->pairs, dict_enum->cur);
}
}
}
static HRESULT WINAPI dictionary_QueryInterface(IDictionary *iface, REFIID riid, void **obj)
{
dictionary *This = impl_from_IDictionary(iface);
@ -81,8 +411,10 @@ static ULONG WINAPI dictionary_Release(IDictionary *iface)
TRACE("(%p)\n", This);
ref = InterlockedDecrement(&This->ref);
if(ref == 0)
if(ref == 0) {
IDictionary_RemoveAll(iface);
heap_free(This);
}
return ref;
}
@ -155,135 +487,361 @@ static HRESULT WINAPI dictionary_putref_Item(IDictionary *iface, VARIANT *Key, V
return E_NOTIMPL;
}
static HRESULT WINAPI dictionary_put_Item(IDictionary *iface, VARIANT *Key, VARIANT *pRetItem)
static HRESULT WINAPI dictionary_put_Item(IDictionary *iface, VARIANT *key, VARIANT *item)
{
dictionary *This = impl_from_IDictionary(iface);
struct keyitem_pair *pair;
FIXME("(%p)->(%p %p)\n", This, Key, pRetItem);
TRACE("(%p)->(%s %s)\n", This, debugstr_variant(key), debugstr_variant(item));
return E_NOTIMPL;
if ((pair = get_keyitem_pair(This, key)))
return VariantCopyInd(&pair->item, item);
return IDictionary_Add(iface, key, item);
}
static HRESULT WINAPI dictionary_get_Item(IDictionary *iface, VARIANT *Key, VARIANT *pRetItem)
static HRESULT WINAPI dictionary_get_Item(IDictionary *iface, VARIANT *key, VARIANT *item)
{
dictionary *This = impl_from_IDictionary(iface);
struct keyitem_pair *pair;
FIXME("(%p)->(%p %p)\n", This, Key, pRetItem );
TRACE("(%p)->(%s %p)\n", This, debugstr_variant(key), item);
return E_NOTIMPL;
}
static HRESULT WINAPI dictionary_Add(IDictionary *iface, VARIANT *Key, VARIANT *Item)
{
dictionary *This = impl_from_IDictionary(iface);
FIXME("(%p)->(%p %p)\n", This, Key, Item);
return E_NOTIMPL;
}
static HRESULT WINAPI dictionary_get_Count(IDictionary *iface, LONG *pCount)
{
dictionary *This = impl_from_IDictionary(iface);
FIXME("(%p)->(%p)\n", This, pCount);
*pCount = 0;
if ((pair = get_keyitem_pair(This, key)))
VariantCopy(item, &pair->item);
else {
VariantInit(item);
return IDictionary_Add(iface, key, item);
}
return S_OK;
}
static HRESULT WINAPI dictionary_Exists(IDictionary *iface, VARIANT *Key, VARIANT_BOOL *pExists)
static HRESULT WINAPI dictionary_Add(IDictionary *iface, VARIANT *key, VARIANT *item)
{
dictionary *This = impl_from_IDictionary(iface);
FIXME("(%p)->(%p %p)\n", This, Key, pExists);
TRACE("(%p)->(%s %s)\n", This, debugstr_variant(key), debugstr_variant(item));
return E_NOTIMPL;
if (get_keyitem_pair(This, key))
return CTL_E_KEY_ALREADY_EXISTS;
return add_keyitem_pair(This, key, item);
}
static HRESULT WINAPI dictionary_Items(IDictionary *iface, VARIANT *pItemsArray)
static HRESULT WINAPI dictionary_get_Count(IDictionary *iface, LONG *count)
{
dictionary *This = impl_from_IDictionary(iface);
FIXME("(%p)->(%p)\n", This, pItemsArray);
TRACE("(%p)->(%p)\n", This, count);
return E_NOTIMPL;
*count = This->count;
return S_OK;
}
static HRESULT WINAPI dictionary_put_Key(IDictionary *iface, VARIANT *Key, VARIANT *rhs)
static HRESULT WINAPI dictionary_Exists(IDictionary *iface, VARIANT *key, VARIANT_BOOL *exists)
{
dictionary *This = impl_from_IDictionary(iface);
FIXME("(%p)->(%p %p)\n", This, Key, rhs);
TRACE("(%p)->(%s %p)\n", This, debugstr_variant(key), exists);
return E_NOTIMPL;
if (!exists)
return CTL_E_ILLEGALFUNCTIONCALL;
*exists = get_keyitem_pair(This, key) != NULL ? VARIANT_TRUE : VARIANT_FALSE;
return S_OK;
}
static HRESULT WINAPI dictionary_Keys(IDictionary *iface, VARIANT *pKeysArray)
static HRESULT WINAPI dictionary_Items(IDictionary *iface, VARIANT *items)
{
dictionary *This = impl_from_IDictionary(iface);
struct keyitem_pair *pair;
SAFEARRAYBOUND bound;
SAFEARRAY *sa;
VARIANT *v;
HRESULT hr;
LONG i;
FIXME("(%p)->(%p)\n", This, pKeysArray);
TRACE("(%p)->(%p)\n", This, items);
return E_NOTIMPL;
if (!items)
return S_OK;
bound.lLbound = 0;
bound.cElements = This->count;
sa = SafeArrayCreate(VT_VARIANT, 1, &bound);
if (!sa)
return E_OUTOFMEMORY;
hr = SafeArrayAccessData(sa, (void**)&v);
if (FAILED(hr)) {
SafeArrayDestroy(sa);
return hr;
}
i = 0;
LIST_FOR_EACH_ENTRY(pair, &This->pairs, struct keyitem_pair, entry) {
VariantCopy(&v[i], &pair->item);
i++;
}
SafeArrayUnaccessData(sa);
V_VT(items) = VT_ARRAY|VT_VARIANT;
V_ARRAY(items) = sa;
return S_OK;
}
static HRESULT WINAPI dictionary_Remove(IDictionary *iface, VARIANT *Key)
static HRESULT WINAPI dictionary_put_Key(IDictionary *iface, VARIANT *key, VARIANT *newkey)
{
dictionary *This = impl_from_IDictionary(iface);
struct keyitem_pair *pair;
VARIANT empty;
HRESULT hr;
FIXME("(%p)->(%p)\n", This, Key);
TRACE("(%p)->(%s %s)\n", This, debugstr_variant(key), debugstr_variant(newkey));
return E_NOTIMPL;
if ((pair = get_keyitem_pair(This, key))) {
/* found existing pair for a key, add new pair with new key
and old item and remove old pair after that */
hr = IDictionary_Add(iface, newkey, &pair->item);
if (FAILED(hr))
return hr;
return IDictionary_Remove(iface, key);
}
VariantInit(&empty);
return IDictionary_Add(iface, newkey, &empty);
}
static HRESULT WINAPI dictionary_Keys(IDictionary *iface, VARIANT *keys)
{
dictionary *This = impl_from_IDictionary(iface);
struct keyitem_pair *pair;
SAFEARRAYBOUND bound;
SAFEARRAY *sa;
VARIANT *v;
HRESULT hr;
LONG i;
TRACE("(%p)->(%p)\n", This, keys);
if (!keys)
return S_OK;
bound.lLbound = 0;
bound.cElements = This->count;
sa = SafeArrayCreate(VT_VARIANT, 1, &bound);
if (!sa)
return E_OUTOFMEMORY;
hr = SafeArrayAccessData(sa, (void**)&v);
if (FAILED(hr)) {
SafeArrayDestroy(sa);
return hr;
}
i = 0;
LIST_FOR_EACH_ENTRY(pair, &This->pairs, struct keyitem_pair, entry) {
VariantCopy(&v[i], &pair->key);
i++;
}
SafeArrayUnaccessData(sa);
V_VT(keys) = VT_ARRAY|VT_VARIANT;
V_ARRAY(keys) = sa;
return S_OK;
}
static HRESULT WINAPI dictionary_Remove(IDictionary *iface, VARIANT *key)
{
dictionary *This = impl_from_IDictionary(iface);
struct keyitem_pair *pair;
TRACE("(%p)->(%s)\n", This, debugstr_variant(key));
if (!(pair = get_keyitem_pair(This, key)))
return CTL_E_ELEMENT_NOT_FOUND;
notify_remove_pair(&This->notifier, &pair->entry);
list_remove(&pair->entry);
list_remove(&pair->bucket);
This->count--;
free_keyitem_pair(pair);
return S_OK;
}
static HRESULT WINAPI dictionary_RemoveAll(IDictionary *iface)
{
dictionary *This = impl_from_IDictionary(iface);
struct keyitem_pair *pair, *pair2;
FIXME("(%p)->()\n", This);
TRACE("(%p)\n", This);
return E_NOTIMPL;
if (This->count == 0)
return S_OK;
notify_remove_pair(&This->notifier, NULL);
LIST_FOR_EACH_ENTRY_SAFE(pair, pair2, &This->pairs, struct keyitem_pair, entry) {
list_remove(&pair->entry);
list_remove(&pair->bucket);
free_keyitem_pair(pair);
}
This->count = 0;
return S_OK;
}
static HRESULT WINAPI dictionary_put_CompareMode(IDictionary *iface, CompareMethod pcomp)
static HRESULT WINAPI dictionary_put_CompareMode(IDictionary *iface, CompareMethod method)
{
dictionary *This = impl_from_IDictionary(iface);
FIXME("(%p)->()\n", This);
TRACE("(%p)->(%d)\n", This, method);
return E_NOTIMPL;
if (This->count)
return CTL_E_ILLEGALFUNCTIONCALL;
This->method = method;
return S_OK;
}
static HRESULT WINAPI dictionary_get_CompareMode(IDictionary *iface, CompareMethod *pcomp)
static HRESULT WINAPI dictionary_get_CompareMode(IDictionary *iface, CompareMethod *method)
{
dictionary *This = impl_from_IDictionary(iface);
FIXME("(%p)->(%p)\n", This, pcomp);
TRACE("(%p)->(%p)\n", This, method);
return E_NOTIMPL;
*method = This->method;
return S_OK;
}
static HRESULT WINAPI dictionary__NewEnum(IDictionary *iface, IUnknown **ppunk)
static HRESULT WINAPI dictionary__NewEnum(IDictionary *iface, IUnknown **ret)
{
dictionary *This = impl_from_IDictionary(iface);
FIXME("(%p)->(%p)\n", This, ppunk);
TRACE("(%p)->(%p)\n", This, ret);
return E_NOTIMPL;
return create_dict_enum(This, ret);
}
static HRESULT WINAPI dictionary_get_HashVal(IDictionary *iface, VARIANT *Key, VARIANT *HashVal)
static DWORD get_str_hash(const WCHAR *str, CompareMethod method)
{
DWORD hash = 0;
if (str) {
while (*str) {
WCHAR ch;
ch = (method == TextCompare || method == DatabaseCompare) ? tolowerW(*str) : *str;
hash += (hash << 4) + ch;
str++;
}
}
return hash % DICT_HASH_MOD;
}
static DWORD get_num_hash(FLOAT num)
{
return (*((DWORD*)&num)) % DICT_HASH_MOD;
}
static HRESULT get_flt_hash(FLOAT flt, LONG *hash)
{
if (isinf(flt)) {
*hash = 0;
return S_OK;
}
else if (!isnan(flt)) {
*hash = get_num_hash(flt);
return S_OK;
}
/* NaN case */
*hash = ~0u;
return CTL_E_ILLEGALFUNCTIONCALL;
}
static DWORD get_ptr_hash(void *ptr)
{
return PtrToUlong(ptr) % DICT_HASH_MOD;
}
static HRESULT WINAPI dictionary_get_HashVal(IDictionary *iface, VARIANT *key, VARIANT *hash)
{
dictionary *This = impl_from_IDictionary(iface);
FIXME("(%p)->(%p %p)\n", This, Key, HashVal);
TRACE("(%p)->(%s %p)\n", This, debugstr_variant(key), hash);
return E_NOTIMPL;
V_VT(hash) = VT_I4;
switch (V_VT(key))
{
case VT_BSTR|VT_BYREF:
case VT_BSTR:
V_I4(hash) = get_str_hash(get_key_strptr(key), This->method);
break;
case VT_UI1|VT_BYREF:
case VT_UI1:
V_I4(hash) = get_num_hash(V_VT(key) & VT_BYREF ? *V_UI1REF(key) : V_UI1(key));
break;
case VT_I2|VT_BYREF:
case VT_I2:
V_I4(hash) = get_num_hash(V_VT(key) & VT_BYREF ? *V_I2REF(key) : V_I2(key));
break;
case VT_I4|VT_BYREF:
case VT_I4:
V_I4(hash) = get_num_hash(V_VT(key) & VT_BYREF ? *V_I4REF(key) : V_I4(key));
break;
case VT_UNKNOWN|VT_BYREF:
case VT_DISPATCH|VT_BYREF:
case VT_UNKNOWN:
case VT_DISPATCH:
{
IUnknown *src = (V_VT(key) & VT_BYREF) ? *V_UNKNOWNREF(key) : V_UNKNOWN(key);
IUnknown *unk = NULL;
if (!src) {
V_I4(hash) = 0;
return S_OK;
}
IUnknown_QueryInterface(src, &IID_IUnknown, (void**)&unk);
if (!unk) {
V_I4(hash) = ~0u;
return CTL_E_ILLEGALFUNCTIONCALL;
}
V_I4(hash) = get_ptr_hash(unk);
IUnknown_Release(unk);
break;
}
case VT_DATE|VT_BYREF:
case VT_DATE:
return get_flt_hash(V_VT(key) & VT_BYREF ? *V_DATEREF(key) : V_DATE(key), &V_I4(hash));
case VT_R4|VT_BYREF:
case VT_R4:
return get_flt_hash(V_VT(key) & VT_BYREF ? *V_R4REF(key) : V_R4(key), &V_I4(hash));
case VT_R8|VT_BYREF:
case VT_R8:
return get_flt_hash(V_VT(key) & VT_BYREF ? *V_R8REF(key) : V_R8(key), &V_I4(hash));
case VT_INT:
case VT_UINT:
case VT_I1:
case VT_I8:
case VT_UI2:
case VT_UI4:
V_I4(hash) = ~0u;
return CTL_E_ILLEGALFUNCTIONCALL;
default:
FIXME("not implemented for type %d\n", V_VT(key));
return E_NOTIMPL;
}
return S_OK;
}
static const struct IDictionaryVtbl dictionary_vtbl =
{
dictionary_QueryInterface,
@ -323,6 +881,11 @@ HRESULT WINAPI Dictionary_CreateInstance(IClassFactory *factory,IUnknown *outer,
This->IDictionary_iface.lpVtbl = &dictionary_vtbl;
This->ref = 1;
This->method = BinaryCompare;
This->count = 0;
list_init(&This->pairs);
list_init(&This->notifier);
memset(This->buckets, 0, sizeof(This->buckets));
*obj = &This->IDictionary_iface;

View file

@ -620,8 +620,16 @@ static HRESULT WINAPI textstream_SkipLine(ITextStream *iface)
static HRESULT WINAPI textstream_Close(ITextStream *iface)
{
struct textstream *This = impl_from_ITextStream(iface);
FIXME("(%p): stub\n", This);
return E_NOTIMPL;
HRESULT hr = S_OK;
TRACE("(%p)\n", This);
if(!CloseHandle(This->file))
hr = S_FALSE;
This->file = NULL;
return hr;
}
static const ITextStreamVtbl textstreamvtbl = {
@ -2533,11 +2541,20 @@ static HRESULT WINAPI file_Invoke(IFile *iface, DISPID dispIdMember, REFIID riid
return hr;
}
static HRESULT WINAPI file_get_Path(IFile *iface, BSTR *pbstrPath)
static HRESULT WINAPI file_get_Path(IFile *iface, BSTR *path)
{
struct file *This = impl_from_IFile(iface);
FIXME("(%p)->(%p)\n", This, pbstrPath);
return E_NOTIMPL;
TRACE("(%p)->(%p)\n", This, path);
if (!path)
return E_POINTER;
*path = SysAllocString(This->path);
if (!*path)
return E_OUTOFMEMORY;
return S_OK;
}
static HRESULT WINAPI file_get_Name(IFile *iface, BSTR *name)
@ -2623,8 +2640,10 @@ static HRESULT WINAPI file_get_Attributes(IFile *iface, FileAttribute *pfa)
static HRESULT WINAPI file_put_Attributes(IFile *iface, FileAttribute pfa)
{
struct file *This = impl_from_IFile(iface);
FIXME("(%p)->(%x)\n", This, pfa);
return E_NOTIMPL;
TRACE("(%p)->(%x)\n", This, pfa);
return SetFileAttributesW(This->path, pfa) ? S_OK : create_error(GetLastError());
}
static HRESULT WINAPI file_get_DateCreated(IFile *iface, DATE *pdate)
@ -3090,12 +3109,26 @@ static HRESULT WINAPI filesys_GetBaseName(IFileSystem3 *iface, BSTR Path,
return S_OK;
}
static HRESULT WINAPI filesys_GetExtensionName(IFileSystem3 *iface, BSTR Path,
BSTR *pbstrResult)
static HRESULT WINAPI filesys_GetExtensionName(IFileSystem3 *iface, BSTR path,
BSTR *ext)
{
FIXME("%p %s %p\n", iface, debugstr_w(Path), pbstrResult);
INT len;
return E_NOTIMPL;
TRACE("%p %s %p\n", iface, debugstr_w(path), ext);
*ext = NULL;
len = SysStringLen(path);
while (len) {
if (path[len-1] == '.') {
*ext = SysAllocString(&path[len]);
if (!*ext)
return E_OUTOFMEMORY;
break;
}
len--;
}
return S_OK;
}
static HRESULT WINAPI filesys_GetAbsolutePathName(IFileSystem3 *iface, BSTR Path,
@ -3249,11 +3282,41 @@ static HRESULT WINAPI filesys_GetFolder(IFileSystem3 *iface, BSTR FolderPath,
static HRESULT WINAPI filesys_GetSpecialFolder(IFileSystem3 *iface,
SpecialFolderConst SpecialFolder,
IFolder **ppfolder)
IFolder **folder)
{
FIXME("%p %d %p\n", iface, SpecialFolder, ppfolder);
WCHAR pathW[MAX_PATH];
DWORD ret;
return E_NOTIMPL;
TRACE("%p %d %p\n", iface, SpecialFolder, folder);
if (!folder)
return E_POINTER;
*folder = NULL;
switch (SpecialFolder)
{
case WindowsFolder:
ret = GetWindowsDirectoryW(pathW, sizeof(pathW)/sizeof(WCHAR));
break;
case SystemFolder:
ret = GetSystemDirectoryW(pathW, sizeof(pathW)/sizeof(WCHAR));
break;
case TemporaryFolder:
ret = GetTempPathW(sizeof(pathW)/sizeof(WCHAR), pathW);
/* we don't want trailing backslash */
if (ret && pathW[ret-1] == '\\')
pathW[ret-1] = 0;
break;
default:
FIXME("unknown special folder type, %d\n", SpecialFolder);
return E_INVALIDARG;
}
if (!ret)
return HRESULT_FROM_WIN32(GetLastError());
return create_folder(pathW, folder);
}
static inline HRESULT delete_file(const WCHAR *file, DWORD file_len, VARIANT_BOOL force)

View file

@ -202,11 +202,11 @@ HRESULT WINAPI DllUnregisterServer(void)
HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
{
if(IsEqualGUID(&CLSID_FileSystemObject, rclsid)) {
TRACE("(CLSID_WshShell %s %p)\n", debugstr_guid(riid), ppv);
TRACE("(CLSID_FileSystemObject %s %p)\n", debugstr_guid(riid), ppv);
return IClassFactory_QueryInterface(&FileSystemFactory, riid, ppv);
}
else if(IsEqualGUID(&CLSID_Dictionary, rclsid)) {
TRACE("(CLSID_WshShell %s %p)\n", debugstr_guid(riid), ppv);
TRACE("(CLSID_Dictionary %s %p)\n", debugstr_guid(riid), ppv);
return IClassFactory_QueryInterface(&DictionaryFactory, riid, ppv);
}

View file

@ -27,7 +27,10 @@ cpp_quote("#undef CopyFile")
cpp_quote("#undef DeleteFile")
cpp_quote("#undef MoveFile")
cpp_quote("#endif")
cpp_quote("#define CTL_E_ENDOFFILE STD_CTL_SCODE(62)") /* this is not defined in public headers */
/* this is not defined in public headers */
cpp_quote("#define CTL_E_ENDOFFILE STD_CTL_SCODE(62)")
cpp_quote("#define CTL_E_KEY_ALREADY_EXISTS STD_CTL_SCODE(457)")
cpp_quote("#define CTL_E_ELEMENT_NOT_FOUND STD_CTL_SCODE(32811)")
[
uuid(420B2830-E718-11CF-893D-00A0C9054228),

View file

@ -171,7 +171,7 @@ reactos/dll/win32/rsabase # Synced to WineStaging-1.7.37
reactos/dll/win32/rsaenh # Synced to WineStaging-1.7.47
reactos/dll/win32/sccbase # Synced to WineStaging-1.7.37
reactos/dll/win32/schannel # Synced to WineStaging-1.7.37
reactos/dll/win32/scrrun # Synced to WineStaging-1.7.37
reactos/dll/win32/scrrun # Synced to WineStaging-1.7.47
reactos/dll/win32/secur32 # Forked
reactos/dll/win32/security # Forked (different .spec)
reactos/dll/win32/sensapi # Synced to WineStaging-1.7.37