Commit cdd932a0 authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

ole32: Separate IIDFromString() for CLSIDFromString(), fix corner cases and return values.

parent d1c48710
......@@ -2065,33 +2065,16 @@ static inline BOOL is_valid_hex(WCHAR c)
return TRUE;
}
/******************************************************************************
* CLSIDFromString [OLE32.@]
* IIDFromString [OLE32.@]
*
* Converts a unique identifier from its string representation into
* the GUID struct.
*
* PARAMS
* idstr [I] The string representation of the GUID.
* id [O] GUID converted from the string.
*
* RETURNS
* S_OK on success
* CO_E_CLASSSTRING if idstr is not a valid CLSID
*
* SEE ALSO
* StringFromCLSID
*/
static HRESULT __CLSIDFromString(LPCWSTR s, LPCLSID id)
/* conversion helper for CLSIDFromString/IIDFromString */
static BOOL guid_from_string(LPCWSTR s, GUID *id)
{
int i;
BYTE table[256];
if (!s || s[0]!='{') {
memset( id, 0, sizeof (CLSID) );
if(!s) return S_OK;
return CO_E_CLASSSTRING;
if(!s) return TRUE;
return FALSE;
}
TRACE("%s -> %p\n", debugstr_w(s), id);
......@@ -2111,38 +2094,38 @@ static HRESULT __CLSIDFromString(LPCWSTR s, LPCLSID id)
id->Data1 = 0;
for (i = 1; i < 9; i++) {
if (!is_valid_hex(s[i])) return CO_E_CLASSSTRING;
if (!is_valid_hex(s[i])) return FALSE;
id->Data1 = (id->Data1 << 4) | table[s[i]];
}
if (s[9]!='-') return CO_E_CLASSSTRING;
if (s[9]!='-') return FALSE;
id->Data2 = 0;
for (i = 10; i < 14; i++) {
if (!is_valid_hex(s[i])) return CO_E_CLASSSTRING;
if (!is_valid_hex(s[i])) return FALSE;
id->Data2 = (id->Data2 << 4) | table[s[i]];
}
if (s[14]!='-') return CO_E_CLASSSTRING;
if (s[14]!='-') return FALSE;
id->Data3 = 0;
for (i = 15; i < 19; i++) {
if (!is_valid_hex(s[i])) return CO_E_CLASSSTRING;
if (!is_valid_hex(s[i])) return FALSE;
id->Data3 = (id->Data3 << 4) | table[s[i]];
}
if (s[19]!='-') return CO_E_CLASSSTRING;
if (s[19]!='-') return FALSE;
for (i = 20; i < 37; i+=2) {
if (i == 24) {
if (s[i]!='-') return CO_E_CLASSSTRING;
if (s[i]!='-') return FALSE;
i++;
}
if (!is_valid_hex(s[i]) || !is_valid_hex(s[i+1])) return CO_E_CLASSSTRING;
if (!is_valid_hex(s[i]) || !is_valid_hex(s[i+1])) return FALSE;
id->Data4[(i-20)/2] = table[s[i]] << 4 | table[s[i+1]];
}
if (s[37] == '}' && s[38] == '\0')
return S_OK;
return TRUE;
return CO_E_CLASSSTRING;
return FALSE;
}
/*****************************************************************************/
......@@ -2157,6 +2140,7 @@ static HRESULT clsid_from_string_reg(LPCOLESTR progid, CLSID *clsid)
memset(clsid, 0, sizeof(*clsid));
buf = HeapAlloc( GetProcessHeap(),0,(strlenW(progid)+8) * sizeof(WCHAR) );
if (!buf) return E_OUTOFMEMORY;
strcpyW( buf, progid );
strcatW( buf, clsidW );
if (open_classes_key(HKEY_CLASSES_ROOT, buf, MAXIMUM_ALLOWED, &xhkey))
......@@ -2174,26 +2158,81 @@ static HRESULT clsid_from_string_reg(LPCOLESTR progid, CLSID *clsid)
return CO_E_CLASSSTRING;
}
RegCloseKey(xhkey);
return __CLSIDFromString(buf2,clsid);
return guid_from_string(buf2, clsid) ? S_OK : CO_E_CLASSSTRING;
}
/******************************************************************************
* CLSIDFromString [OLE32.@]
*
* Converts a unique identifier from its string representation into
* the GUID struct.
*
* PARAMS
* idstr [I] The string representation of the GUID.
* id [O] GUID converted from the string.
*
* RETURNS
* S_OK on success
* CO_E_CLASSSTRING if idstr is not a valid CLSID
*
* SEE ALSO
* StringFromCLSID
*/
HRESULT WINAPI CLSIDFromString(LPCOLESTR idstr, LPCLSID id )
{
HRESULT ret;
HRESULT ret = CO_E_CLASSSTRING;
CLSID tmp_id;
if (!id)
return E_INVALIDARG;
ret = __CLSIDFromString(idstr, id);
if(ret != S_OK) { /* It appears a ProgID is also valid */
CLSID tmp_id;
if (guid_from_string(idstr, id))
return S_OK;
/* It appears a ProgID is also valid */
ret = clsid_from_string_reg(idstr, &tmp_id);
if(SUCCEEDED(ret))
*id = tmp_id;
}
return ret;
}
/******************************************************************************
* IIDFromString [OLE32.@]
*
* Converts a interface identifier from its string representation into
* the IID struct.
*
* PARAMS
* idstr [I] The string representation of the GUID.
* id [O] IID converted from the string.
*
* RETURNS
* S_OK on success
* CO_E_IIDSTRING if idstr is not a valid IID
*
* SEE ALSO
* StringFromIID
*/
HRESULT WINAPI IIDFromString(LPCOLESTR s, IID *iid)
{
TRACE("%s -> %p\n", debugstr_w(s), iid);
if (!s)
{
memset(iid, 0, sizeof(*iid));
return S_OK;
}
/* length mismatch is a special case */
if (strlenW(s) + 1 != CHARS_IN_GUID)
return E_INVALIDARG;
if (s[0] != '{')
return CO_E_IIDSTRING;
return guid_from_string(s, iid) ? S_OK : CO_E_IIDSTRING;
}
/******************************************************************************
* StringFromCLSID [OLE32.@]
......
......@@ -164,7 +164,7 @@
@ stdcall HWND_UserMarshal(ptr ptr ptr)
@ stdcall HWND_UserSize(ptr long ptr)
@ stdcall HWND_UserUnmarshal(ptr ptr ptr)
@ stdcall IIDFromString(wstr ptr) CLSIDFromString
@ stdcall IIDFromString(wstr ptr)
@ stub I_RemoteMain
@ stdcall IsAccelerator(long long ptr long)
@ stdcall IsEqualGUID(ptr ptr)
......
......@@ -73,6 +73,8 @@ static const WCHAR wszCLSID_StdFont[] =
'9','d','e','3','-','0','0','a','a','0','0','4','b','b','8','5','1','}',0
};
static const WCHAR progidW[] = {'P','r','o','g','I','d','.','P','r','o','g','I','d',0};
static const WCHAR cf_brokenW[] = {'{','0','0','0','0','0','0','0','1','-','0','0','0','0','-','0','0','0','0','-',
'c','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}','a',0};
DEFINE_GUID(IID_IWineTest, 0x5201163f, 0x8164, 0x4fd0, 0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd);
DEFINE_GUID(CLSID_WineOOPTest, 0x5201163f, 0x8164, 0x4fd0, 0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd);
......@@ -396,10 +398,17 @@ static void test_CLSIDFromString(void)
ok_ole_success(hr, "CLSIDFromString");
ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
memset(&clsid, 0xab, sizeof(clsid));
hr = CLSIDFromString(NULL, &clsid);
ok_ole_success(hr, "CLSIDFromString");
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(IsEqualCLSID(&clsid, &CLSID_NULL), "clsid wasn't equal to CLSID_NULL\n");
/* string is longer, but starts with a valid CLSID */
memset(&clsid, 0, sizeof(clsid));
hr = CLSIDFromString(cf_brokenW, &clsid);
ok(hr == CO_E_CLASSSTRING, "got 0x%08x\n", hr);
ok(IsEqualCLSID(&clsid, &IID_IClassFactory), "got %s\n", wine_dbgstr_guid(&clsid));
lstrcpyW(wszCLSID_Broken, wszCLSID_StdFont);
for(i = lstrlenW(wszCLSID_StdFont); i < 49; i++)
wszCLSID_Broken[i] = 'A';
......@@ -455,6 +464,68 @@ static void test_CLSIDFromString(void)
ok(clsid.Data2 == 0xcccc, "Got %04x\n", clsid.Data2);
}
static void test_IIDFromString(void)
{
static const WCHAR cfW[] = {'{','0','0','0','0','0','0','0','1','-','0','0','0','0','-','0','0','0','0','-',
'c','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}',0};
static const WCHAR brokenW[] = {'{','0','0','0','0','0','0','0','1','-','0','0','0','0','-','0','0','0','0','-',
'g','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}',0};
static const WCHAR broken2W[] = {'{','0','0','0','0','0','0','0','1','=','0','0','0','0','-','0','0','0','0','-',
'g','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}',0};
static const WCHAR broken3W[] = {'b','r','o','k','e','n','0','0','1','=','0','0','0','0','-','0','0','0','0','-',
'g','0','0','0','-','0','0','0','0','0','0','0','0','0','0','4','6','}',0};
HRESULT hr;
IID iid;
hr = IIDFromString(wszCLSID_StdFont, &iid);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(IsEqualIID(&iid, &CLSID_StdFont), "got iid %s\n", wine_dbgstr_guid(&iid));
memset(&iid, 0xab, sizeof(iid));
hr = IIDFromString(NULL, &iid);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(IsEqualIID(&iid, &CLSID_NULL), "got iid %s\n", wine_dbgstr_guid(&iid));
hr = IIDFromString(cfW, &iid);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(IsEqualIID(&iid, &IID_IClassFactory), "got iid %s\n", wine_dbgstr_guid(&iid));
/* string starts with a valid IID but is longer */
memset(&iid, 0xab, sizeof(iid));
hr = IIDFromString(cf_brokenW, &iid);
ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
ok(iid.Data1 == 0xabababab, "Got %08x\n", iid.Data1);
/* invalid IID in a valid format */
memset(&iid, 0xab, sizeof(iid));
hr = IIDFromString(brokenW, &iid);
ok(hr == CO_E_IIDSTRING, "got 0x%08x\n", hr);
ok(iid.Data1 == 0x00000001, "Got %08x\n", iid.Data1);
memset(&iid, 0xab, sizeof(iid));
hr = IIDFromString(broken2W, &iid);
ok(hr == CO_E_IIDSTRING, "got 0x%08x\n", hr);
ok(iid.Data1 == 0x00000001, "Got %08x\n", iid.Data1);
/* format is broken, but string length is okay */
memset(&iid, 0xab, sizeof(iid));
hr = IIDFromString(broken3W, &iid);
ok(hr == CO_E_IIDSTRING, "got 0x%08x\n", hr);
ok(iid.Data1 == 0xabababab, "Got %08x\n", iid.Data1);
/* invalid string */
memset(&iid, 0xab, sizeof(iid));
hr = IIDFromString(wszNonExistent, &iid);
ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
ok(iid.Data1 == 0xabababab, "Got %08x\n", iid.Data1);
/* valid ProgID */
memset(&iid, 0xab, sizeof(iid));
hr = IIDFromString(stdfont, &iid);
ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
ok(iid.Data1 == 0xabababab, "Got %08x\n", iid.Data1);
}
static void test_StringFromGUID2(void)
{
WCHAR str[50];
......@@ -1932,6 +2003,7 @@ START_TEST(compobj)
test_ProgIDFromCLSID();
test_CLSIDFromProgID();
test_CLSIDFromString();
test_IIDFromString();
test_StringFromGUID2();
test_CoCreateInstance();
test_ole_menu();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment