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) ...@@ -2065,33 +2065,16 @@ static inline BOOL is_valid_hex(WCHAR c)
return TRUE; return TRUE;
} }
/****************************************************************************** /* conversion helper for CLSIDFromString/IIDFromString */
* CLSIDFromString [OLE32.@] static BOOL guid_from_string(LPCWSTR s, GUID *id)
* 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)
{ {
int i; int i;
BYTE table[256]; BYTE table[256];
if (!s || s[0]!='{') { if (!s || s[0]!='{') {
memset( id, 0, sizeof (CLSID) ); memset( id, 0, sizeof (CLSID) );
if(!s) return S_OK; if(!s) return TRUE;
return CO_E_CLASSSTRING; return FALSE;
} }
TRACE("%s -> %p\n", debugstr_w(s), id); TRACE("%s -> %p\n", debugstr_w(s), id);
...@@ -2111,38 +2094,38 @@ static HRESULT __CLSIDFromString(LPCWSTR s, LPCLSID id) ...@@ -2111,38 +2094,38 @@ static HRESULT __CLSIDFromString(LPCWSTR s, LPCLSID id)
id->Data1 = 0; id->Data1 = 0;
for (i = 1; i < 9; i++) { 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]]; id->Data1 = (id->Data1 << 4) | table[s[i]];
} }
if (s[9]!='-') return CO_E_CLASSSTRING; if (s[9]!='-') return FALSE;
id->Data2 = 0; id->Data2 = 0;
for (i = 10; i < 14; i++) { 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]]; id->Data2 = (id->Data2 << 4) | table[s[i]];
} }
if (s[14]!='-') return CO_E_CLASSSTRING; if (s[14]!='-') return FALSE;
id->Data3 = 0; id->Data3 = 0;
for (i = 15; i < 19; i++) { 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]]; 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) { for (i = 20; i < 37; i+=2) {
if (i == 24) { if (i == 24) {
if (s[i]!='-') return CO_E_CLASSSTRING; if (s[i]!='-') return FALSE;
i++; 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]]; id->Data4[(i-20)/2] = table[s[i]] << 4 | table[s[i+1]];
} }
if (s[37] == '}' && s[38] == '\0') 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) ...@@ -2157,6 +2140,7 @@ static HRESULT clsid_from_string_reg(LPCOLESTR progid, CLSID *clsid)
memset(clsid, 0, sizeof(*clsid)); memset(clsid, 0, sizeof(*clsid));
buf = HeapAlloc( GetProcessHeap(),0,(strlenW(progid)+8) * sizeof(WCHAR) ); buf = HeapAlloc( GetProcessHeap(),0,(strlenW(progid)+8) * sizeof(WCHAR) );
if (!buf) return E_OUTOFMEMORY;
strcpyW( buf, progid ); strcpyW( buf, progid );
strcatW( buf, clsidW ); strcatW( buf, clsidW );
if (open_classes_key(HKEY_CLASSES_ROOT, buf, MAXIMUM_ALLOWED, &xhkey)) 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) ...@@ -2174,26 +2158,81 @@ static HRESULT clsid_from_string_reg(LPCOLESTR progid, CLSID *clsid)
return CO_E_CLASSSTRING; return CO_E_CLASSSTRING;
} }
RegCloseKey(xhkey); 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 WINAPI CLSIDFromString(LPCOLESTR idstr, LPCLSID id )
{ {
HRESULT ret; HRESULT ret = CO_E_CLASSSTRING;
CLSID tmp_id;
if (!id) if (!id)
return E_INVALIDARG; return E_INVALIDARG;
ret = __CLSIDFromString(idstr, id); if (guid_from_string(idstr, id))
if(ret != S_OK) { /* It appears a ProgID is also valid */ return S_OK;
CLSID tmp_id;
/* It appears a ProgID is also valid */
ret = clsid_from_string_reg(idstr, &tmp_id); ret = clsid_from_string_reg(idstr, &tmp_id);
if(SUCCEEDED(ret)) if(SUCCEEDED(ret))
*id = tmp_id; *id = tmp_id;
}
return ret; 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.@] * StringFromCLSID [OLE32.@]
......
...@@ -164,7 +164,7 @@ ...@@ -164,7 +164,7 @@
@ stdcall HWND_UserMarshal(ptr ptr ptr) @ stdcall HWND_UserMarshal(ptr ptr ptr)
@ stdcall HWND_UserSize(ptr long ptr) @ stdcall HWND_UserSize(ptr long ptr)
@ stdcall HWND_UserUnmarshal(ptr ptr ptr) @ stdcall HWND_UserUnmarshal(ptr ptr ptr)
@ stdcall IIDFromString(wstr ptr) CLSIDFromString @ stdcall IIDFromString(wstr ptr)
@ stub I_RemoteMain @ stub I_RemoteMain
@ stdcall IsAccelerator(long long ptr long) @ stdcall IsAccelerator(long long ptr long)
@ stdcall IsEqualGUID(ptr ptr) @ stdcall IsEqualGUID(ptr ptr)
......
...@@ -73,6 +73,8 @@ static const WCHAR wszCLSID_StdFont[] = ...@@ -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 '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 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(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); DEFINE_GUID(CLSID_WineOOPTest, 0x5201163f, 0x8164, 0x4fd0, 0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd);
...@@ -396,10 +398,17 @@ static void test_CLSIDFromString(void) ...@@ -396,10 +398,17 @@ static void test_CLSIDFromString(void)
ok_ole_success(hr, "CLSIDFromString"); ok_ole_success(hr, "CLSIDFromString");
ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n"); ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n");
memset(&clsid, 0xab, sizeof(clsid));
hr = CLSIDFromString(NULL, &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"); 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); lstrcpyW(wszCLSID_Broken, wszCLSID_StdFont);
for(i = lstrlenW(wszCLSID_StdFont); i < 49; i++) for(i = lstrlenW(wszCLSID_StdFont); i < 49; i++)
wszCLSID_Broken[i] = 'A'; wszCLSID_Broken[i] = 'A';
...@@ -455,6 +464,68 @@ static void test_CLSIDFromString(void) ...@@ -455,6 +464,68 @@ static void test_CLSIDFromString(void)
ok(clsid.Data2 == 0xcccc, "Got %04x\n", clsid.Data2); 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) static void test_StringFromGUID2(void)
{ {
WCHAR str[50]; WCHAR str[50];
...@@ -1932,6 +2003,7 @@ START_TEST(compobj) ...@@ -1932,6 +2003,7 @@ START_TEST(compobj)
test_ProgIDFromCLSID(); test_ProgIDFromCLSID();
test_CLSIDFromProgID(); test_CLSIDFromProgID();
test_CLSIDFromString(); test_CLSIDFromString();
test_IIDFromString();
test_StringFromGUID2(); test_StringFromGUID2();
test_CoCreateInstance(); test_CoCreateInstance();
test_ole_menu(); 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