ole32: Separate IIDFromString() for CLSIDFromString(), fix corner cases and return values.
This commit is contained in:
parent
d1c4871012
commit
cdd932a060
|
@ -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;
|
||||
ret = clsid_from_string_reg(idstr, &tmp_id);
|
||||
if(SUCCEEDED(ret))
|
||||
*id = 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();
|
||||
|
|
Loading…
Reference in New Issue