Module: wine Branch: master Commit: ea14a6b2e7d6382a4810d616fe2e250091e8ff07 URL: http://source.winehq.org/git/wine.git/?a=commit;h=ea14a6b2e7d6382a4810d616fe...
Author: David Hedberg dhedberg@codeweavers.com Date: Thu Apr 28 15:11:03 2011 +0200
oleaut32: Fix CLSIDToString behaviour when passed an invalid CLSID-string.
In some cases, Excel 2007 apparently relies on CLSIDToString properly parsing an "invalid" CLSID string where extra bytes are appended.
---
dlls/ole32/compobj.c | 82 ++++++++++++++++++++++++++----------------- dlls/ole32/tests/compobj.c | 57 ++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+), 33 deletions(-)
diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c index a637439..0aa3aee 100644 --- a/dlls/ole32/compobj.c +++ b/dlls/ole32/compobj.c @@ -1490,6 +1490,15 @@ HRESULT WINAPI CoCreateGuid(GUID *pguid) return HRESULT_FROM_WIN32( status ); }
+static inline BOOL is_valid_hex(WCHAR c) +{ + if (!(((c >= '0') && (c <= '9')) || + ((c >= 'a') && (c <= 'f')) || + ((c >= 'A') && (c <= 'F')))) + return FALSE; + return TRUE; +} + /****************************************************************************** * CLSIDFromString [OLE32.@] * IIDFromString [OLE32.@] @@ -1513,24 +1522,10 @@ static HRESULT __CLSIDFromString(LPCWSTR s, LPCLSID id) int i; BYTE table[256];
- if (!s) { + if (!s || s[0]!='{') { memset( id, 0, sizeof (CLSID) ); - return S_OK; - } - - /* validate the CLSID string */ - if (strlenW(s) != 38) - return CO_E_CLASSSTRING; - - if ((s[0]!='{') || (s[9]!='-') || (s[14]!='-') || (s[19]!='-') || (s[24]!='-') || (s[37]!='}')) + if(!s) return S_OK; return CO_E_CLASSSTRING; - - for (i=1; i<37; i++) { - if ((i == 9)||(i == 14)||(i == 19)||(i == 24)) continue; - if (!(((s[i] >= '0') && (s[i] <= '9')) || - ((s[i] >= 'a') && (s[i] <= 'f')) || - ((s[i] >= 'A') && (s[i] <= 'F')))) - return CO_E_CLASSSTRING; }
TRACE("%s -> %p\n", debugstr_w(s), id); @@ -1548,22 +1543,40 @@ static HRESULT __CLSIDFromString(LPCWSTR s, LPCLSID id)
/* in form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
- id->Data1 = (table[s[1]] << 28 | table[s[2]] << 24 | table[s[3]] << 20 | table[s[4]] << 16 | - table[s[5]] << 12 | table[s[6]] << 8 | table[s[7]] << 4 | table[s[8]]); - id->Data2 = table[s[10]] << 12 | table[s[11]] << 8 | table[s[12]] << 4 | table[s[13]]; - id->Data3 = table[s[15]] << 12 | table[s[16]] << 8 | table[s[17]] << 4 | table[s[18]]; - - /* these are just sequential bytes */ - id->Data4[0] = table[s[20]] << 4 | table[s[21]]; - id->Data4[1] = table[s[22]] << 4 | table[s[23]]; - id->Data4[2] = table[s[25]] << 4 | table[s[26]]; - id->Data4[3] = table[s[27]] << 4 | table[s[28]]; - id->Data4[4] = table[s[29]] << 4 | table[s[30]]; - id->Data4[5] = table[s[31]] << 4 | table[s[32]]; - id->Data4[6] = table[s[33]] << 4 | table[s[34]]; - id->Data4[7] = table[s[35]] << 4 | table[s[36]]; + id->Data1 = 0; + for (i = 1; i < 9; i++) { + if (!is_valid_hex(s[i])) return CO_E_CLASSSTRING; + id->Data1 = (id->Data1 << 4) | table[s[i]]; + } + if (s[9]!='-') return CO_E_CLASSSTRING;
- return S_OK; + id->Data2 = 0; + for (i = 10; i < 14; i++) { + if (!is_valid_hex(s[i])) return CO_E_CLASSSTRING; + id->Data2 = (id->Data2 << 4) | table[s[i]]; + } + if (s[14]!='-') return CO_E_CLASSSTRING; + + id->Data3 = 0; + for (i = 15; i < 19; i++) { + if (!is_valid_hex(s[i])) return CO_E_CLASSSTRING; + id->Data3 = (id->Data3 << 4) | table[s[i]]; + } + if (s[19]!='-') return CO_E_CLASSSTRING; + + for (i = 20; i < 37; i+=2) { + if (i == 24) { + if (s[i]!='-') return CO_E_CLASSSTRING; + i++; + } + if (!is_valid_hex(s[i]) || !is_valid_hex(s[i+1])) return CO_E_CLASSSTRING; + id->Data4[(i-20)/2] = table[s[i]] << 4 | table[s[i+1]]; + } + + if (s[37] == '}' && s[38] == '\0') + return S_OK; + + return CO_E_CLASSSTRING; }
/*****************************************************************************/ @@ -1577,7 +1590,10 @@ HRESULT WINAPI CLSIDFromString(LPCOLESTR idstr, LPCLSID id )
ret = __CLSIDFromString(idstr, id); if(ret != S_OK) { /* It appears a ProgID is also valid */ - ret = CLSIDFromProgID(idstr, id); + CLSID tmp_id; + ret = CLSIDFromProgID(idstr, &tmp_id); + if(SUCCEEDED(ret)) + *id = tmp_id; } return ret; } diff --git a/dlls/ole32/tests/compobj.c b/dlls/ole32/tests/compobj.c index 3c35fab..53a838e 100644 --- a/dlls/ole32/tests/compobj.c +++ b/dlls/ole32/tests/compobj.c @@ -190,6 +190,9 @@ static void test_CLSIDFromProgID(void) static void test_CLSIDFromString(void) { CLSID clsid; + WCHAR wszCLSID_Broken[50]; + UINT i; + HRESULT hr = CLSIDFromString(wszCLSID_StdFont, &clsid); ok_ole_success(hr, "CLSIDFromString"); ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n"); @@ -197,6 +200,60 @@ static void test_CLSIDFromString(void) hr = CLSIDFromString(NULL, &clsid); ok_ole_success(hr, "CLSIDFromString"); ok(IsEqualCLSID(&clsid, &CLSID_NULL), "clsid wasn't equal to CLSID_NULL\n"); + + lstrcpyW(wszCLSID_Broken, wszCLSID_StdFont); + for(i = lstrlenW(wszCLSID_StdFont); i < 49; i++) + wszCLSID_Broken[i] = 'A'; + wszCLSID_Broken[i] = '\0'; + + memset(&clsid, 0, sizeof(CLSID)); + hr = CLSIDFromString(wszCLSID_Broken, &clsid); + ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr); + ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n"); + + wszCLSID_Broken[lstrlenW(wszCLSID_StdFont)-1] = 'A'; + memset(&clsid, 0, sizeof(CLSID)); + hr = CLSIDFromString(wszCLSID_Broken, &clsid); + ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr); + ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n"); + + wszCLSID_Broken[lstrlenW(wszCLSID_StdFont)] = '\0'; + memset(&clsid, 0, sizeof(CLSID)); + hr = CLSIDFromString(wszCLSID_Broken, &clsid); + ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr); + ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n"); + + wszCLSID_Broken[lstrlenW(wszCLSID_StdFont)-1] = '\0'; + memset(&clsid, 0, sizeof(CLSID)); + hr = CLSIDFromString(wszCLSID_Broken, &clsid); + ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr); + ok(IsEqualCLSID(&clsid, &CLSID_StdFont), "clsid wasn't equal to CLSID_StdFont\n"); + + memset(&clsid, 0xcc, sizeof(CLSID)); + hr = CLSIDFromString(wszCLSID_Broken+1, &clsid); + ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr); + ok(IsEqualCLSID(&clsid, &CLSID_NULL), "clsid wasn't equal to CLSID_NULL\n"); + + wszCLSID_Broken[9] = '*'; + memset(&clsid, 0xcc, sizeof(CLSID)); + hr = CLSIDFromString(wszCLSID_Broken, &clsid); + ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr); + ok(clsid.Data1 == CLSID_StdFont.Data1, "Got %08x\n", clsid.Data1); + ok(clsid.Data2 == 0xcccc, "Got %04x\n", clsid.Data2); + + wszCLSID_Broken[3] = '*'; + memset(&clsid, 0xcc, sizeof(CLSID)); + hr = CLSIDFromString(wszCLSID_Broken, &clsid); + ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr); + ok(clsid.Data1 == 0xb, "Got %08x\n", clsid.Data1); + ok(clsid.Data2 == 0xcccc, "Got %04x\n", clsid.Data2); + + wszCLSID_Broken[3] = '\0'; + memset(&clsid, 0xcc, sizeof(CLSID)); + hr = CLSIDFromString(wszCLSID_Broken, &clsid); + ok(hr == CO_E_CLASSSTRING, "Got %08x\n", hr); + ok(clsid.Data1 == 0xb, "Got %08x\n", clsid.Data1); + ok(clsid.Data2 == 0xcccc, "Got %04x\n", clsid.Data2); }
static void test_StringFromGUID2(void)