From: Andrew Nguyen Subject: [3/4] propsys: Implement PSPropertyKeyFromString. Message-Id: <4C4CF9BF.8000802@codeweavers.com> Date: Sun, 25 Jul 2010 21:58:07 -0500 --- dlls/propsys/propsys.spec | 2 +- dlls/propsys/propsys_main.c | 142 +++++++++++++++++++++++++++++++++++++++++++ include/propsys.idl | 1 + 3 files changed, 144 insertions(+), 1 deletions(-) diff --git a/dlls/propsys/propsys.spec b/dlls/propsys/propsys.spec index cd41d90..10a1cba 100644 --- a/dlls/propsys/propsys.spec +++ b/dlls/propsys/propsys.spec @@ -87,7 +87,7 @@ @ stub PSGetPropertySystem @ stub PSGetPropertyValue @ stub PSLookupPropertyHandlerCLSID -@ stub PSPropertyKeyFromString +@ stdcall PSPropertyKeyFromString(wstr ptr) @ stub PSRefreshPropertySchema @ stdcall PSRegisterPropertySchema(wstr) @ stub PSSetPropertyValue diff --git a/dlls/propsys/propsys_main.c b/dlls/propsys/propsys_main.c index cd180fe..35efda8 100644 --- a/dlls/propsys/propsys_main.c +++ b/dlls/propsys/propsys_main.c @@ -1,6 +1,7 @@ /* * propsys main * + * Copyright 1997, 2002 Alexandre Julliard * Copyright 2008 James Hawkins * * This library is free software; you can redistribute it and/or @@ -130,3 +131,144 @@ HRESULT WINAPI PSStringFromPropertyKey(REFPROPERTYKEY pkey, LPWSTR psz, UINT cch return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); } } + +static const BYTE hex2bin[] = +{ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x00 */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x10 */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x20 */ + 0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0, /* 0x30 */ + 0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0, /* 0x40 */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x50 */ + 0,10,11,12,13,14,15 /* 0x60 */ +}; + +static BOOL validate_indices(LPCWSTR s, int min, int max) +{ + int i; + + for (i = min; i <= max; i++) + { + if (!s[i]) + return FALSE; + + if (i == 0) + { + if (s[i] != '{') + return FALSE; + } + else if (i == 9 || i == 14 || i == 19 || i == 24) + { + if (s[i] != '-') + return FALSE; + } + else if (i == 37) + { + if (s[i] != '}') + return FALSE; + } + else + { + if (s[i] > 'f' || (!hex2bin[s[i]] && s[i] != '0')) + return FALSE; + } + } + + return TRUE; +} + +/* Adapted from CLSIDFromString helper in dlls/ole32/compobj.c and + * UuidFromString in dlls/rpcrt4/rpcrt4_main.c. */ +static BOOL string_to_guid(LPCWSTR s, LPGUID id) +{ + /* in form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */ + + if (!validate_indices(s, 0, 8)) return FALSE; + id->Data1 = (hex2bin[s[1]] << 28 | hex2bin[s[2]] << 24 | hex2bin[s[3]] << 20 | hex2bin[s[4]] << 16 | + hex2bin[s[5]] << 12 | hex2bin[s[6]] << 8 | hex2bin[s[7]] << 4 | hex2bin[s[8]]); + if (!validate_indices(s, 9, 14)) return FALSE; + id->Data2 = hex2bin[s[10]] << 12 | hex2bin[s[11]] << 8 | hex2bin[s[12]] << 4 | hex2bin[s[13]]; + if (!validate_indices(s, 15, 19)) return FALSE; + id->Data3 = hex2bin[s[15]] << 12 | hex2bin[s[16]] << 8 | hex2bin[s[17]] << 4 | hex2bin[s[18]]; + + /* these are just sequential bytes */ + + if (!validate_indices(s, 20, 21)) return FALSE; + id->Data4[0] = hex2bin[s[20]] << 4 | hex2bin[s[21]]; + if (!validate_indices(s, 22, 24)) return FALSE; + id->Data4[1] = hex2bin[s[22]] << 4 | hex2bin[s[23]]; + + if (!validate_indices(s, 25, 26)) return FALSE; + id->Data4[2] = hex2bin[s[25]] << 4 | hex2bin[s[26]]; + if (!validate_indices(s, 27, 28)) return FALSE; + id->Data4[3] = hex2bin[s[27]] << 4 | hex2bin[s[28]]; + if (!validate_indices(s, 29, 30)) return FALSE; + id->Data4[4] = hex2bin[s[29]] << 4 | hex2bin[s[30]]; + if (!validate_indices(s, 31, 32)) return FALSE; + id->Data4[5] = hex2bin[s[31]] << 4 | hex2bin[s[32]]; + if (!validate_indices(s, 33, 34)) return FALSE; + id->Data4[6] = hex2bin[s[33]] << 4 | hex2bin[s[34]]; + if (!validate_indices(s, 35, 37)) return FALSE; + id->Data4[7] = hex2bin[s[35]] << 4 | hex2bin[s[36]]; + + return TRUE; +} + +HRESULT WINAPI PSPropertyKeyFromString(LPCWSTR pszString, PROPERTYKEY *pkey) +{ + int has_minus = 0; + + TRACE("(%s, %p)\n", debugstr_w(pszString), pkey); + + if (!pszString || !pkey) + return E_POINTER; + + memset(pkey, 0, sizeof(PROPERTYKEY)); + + if (!string_to_guid(pszString, &pkey->fmtid)) + return E_INVALIDARG; + + pszString += GUIDSTRING_MAX - 1; + + if (!*pszString) + return E_INVALIDARG; + + /* Only the space seems to be recognized as whitespace. */ + while (*pszString == ' ') + pszString++; + + if (!*pszString) + return E_INVALIDARG; + + /* Only two minus signs are recognized. The first is ignored, and the + * second is interpreted. */ + if (*pszString == '-') + pszString++; + + /* Skip any intermediate spaces after the first minus sign. */ + while (*pszString == ' ') + pszString++; + + if (*pszString == '-') + { + has_minus = 1; + pszString++; + } + + /* Skip any remaining spaces after minus sign. */ + while (*pszString == ' ') + pszString++; + + /* Overflow is not checked. */ + while (isdigitW(*pszString)) + { + pkey->pid *= 10; + pkey->pid += (*pszString - '0'); + pszString++; + } + + if (has_minus) + pkey->pid = ~pkey->pid + 1; + + return S_OK; +} diff --git a/include/propsys.idl b/include/propsys.idl index c098041..da401c5 100644 --- a/include/propsys.idl +++ b/include/propsys.idl @@ -800,6 +800,7 @@ cpp_quote("#define GUIDSTRING_MAX 39") cpp_quote("#define PKEYSTR_MAX (GUIDSTRING_MAX + 1 + PKEY_PIDSTR_MAX)") cpp_quote("HRESULT WINAPI PSStringFromPropertyKey(REFPROPERTYKEY,LPWSTR,UINT);") +cpp_quote("HRESULT WINAPI PSPropertyKeyFromString(LPCWSTR,PROPERTYKEY*);") /* TODO: Add remainder of the C api here */