ole32: Implement MkParseDisplayName.

This commit is contained in:
Rob Shearman 2007-03-27 18:21:23 +01:00 committed by Alexandre Julliard
parent 87a4516bd9
commit f8789122aa
6 changed files with 314 additions and 13 deletions

View File

@ -2,7 +2,7 @@
* Class Monikers
*
* Copyright 1999 Noomen Hamza
* Copyright 2005 Robert Shearman
* Copyright 2005-2007 Robert Shearman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -734,6 +734,87 @@ HRESULT WINAPI CreateClassMoniker(REFCLSID rclsid, IMoniker **ppmk)
return ClassMoniker_QueryInterface((IMoniker *)newClassMoniker, &IID_IMoniker, (void**)ppmk);
}
HRESULT ClassMoniker_CreateFromDisplayName(LPBC pbc, LPCOLESTR szDisplayName,
LPDWORD pchEaten, LPMONIKER *ppmk)
{
HRESULT hr;
LPCWSTR s = strchrW(szDisplayName, ':');
LPCWSTR end;
CLSID clsid;
BYTE table[256];
int i;
if (!s)
return MK_E_SYNTAX;
s++;
for (end = s; *end && (*end != ':'); end++)
;
TRACE("parsing %s\n", debugstr_wn(s, end - s));
/* validate the CLSID string */
if (s[0] == '{')
{
if ((end - s != 38) || (s[37] != '}'))
return MK_E_SYNTAX;
s++;
}
else
{
if (end - s != 36)
return MK_E_SYNTAX;
}
for (i=0; i<36; i++)
{
if ((i == 8)||(i == 13)||(i == 18)||(i == 23))
{
if (s[i] != '-')
return MK_E_SYNTAX;
continue;
}
if (!(((s[i] >= '0') && (s[i] <= '9')) ||
((s[i] >= 'a') && (s[i] <= 'f')) ||
((s[i] >= 'A') && (s[i] <= 'F'))))
return MK_E_SYNTAX;
}
/* quick lookup table */
memset(table, 0, 256);
for (i = 0; i < 10; i++)
table['0' + i] = i;
for (i = 0; i < 6; i++)
{
table['A' + i] = i+10;
table['a' + i] = i+10;
}
/* in form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX */
clsid.Data1 = (table[s[0]] << 28 | table[s[1]] << 24 | table[s[2]] << 20 | table[s[3]] << 16 |
table[s[4]] << 12 | table[s[5]] << 8 | table[s[6]] << 4 | table[s[7]]);
clsid.Data2 = table[s[9]] << 12 | table[s[10]] << 8 | table[s[11]] << 4 | table[s[12]];
clsid.Data3 = table[s[14]] << 12 | table[s[15]] << 8 | table[s[16]] << 4 | table[s[17]];
/* these are just sequential bytes */
clsid.Data4[0] = table[s[19]] << 4 | table[s[20]];
clsid.Data4[1] = table[s[21]] << 4 | table[s[22]];
clsid.Data4[2] = table[s[24]] << 4 | table[s[25]];
clsid.Data4[3] = table[s[26]] << 4 | table[s[27]];
clsid.Data4[4] = table[s[28]] << 4 | table[s[29]];
clsid.Data4[5] = table[s[30]] << 4 | table[s[31]];
clsid.Data4[6] = table[s[32]] << 4 | table[s[33]];
clsid.Data4[7] = table[s[34]] << 4 | table[s[35]];
hr = CreateClassMoniker(&clsid, ppmk);
if (SUCCEEDED(hr))
*pchEaten = (*end == ':' ? end + 1 : end) - szDisplayName;
return hr;
}
static HRESULT WINAPI ClassMonikerCF_QueryInterface(LPCLASSFACTORY iface,
REFIID riid, LPVOID *ppv)
{

View File

@ -1246,6 +1246,7 @@ HRESULT WINAPI CLSIDFromProgID(LPCOLESTR progid, LPCLSID clsid)
if (RegOpenKeyW(HKEY_CLASSES_ROOT,buf,&xhkey))
{
HeapFree(GetProcessHeap(),0,buf);
WARN("couldn't open key for ProgID %s\n", debugstr_w(progid));
return CO_E_CLASSSTRING;
}
HeapFree(GetProcessHeap(),0,buf);
@ -1253,6 +1254,7 @@ HRESULT WINAPI CLSIDFromProgID(LPCOLESTR progid, LPCLSID clsid)
if (RegQueryValueW(xhkey,NULL,buf2,&buf2len))
{
RegCloseKey(xhkey);
WARN("couldn't query clsid value for ProgID %s\n", debugstr_w(progid));
return CO_E_CLASSSTRING;
}
RegCloseKey(xhkey);

View File

@ -2,6 +2,7 @@
* FileMonikers implementation
*
* Copyright 1999 Noomen Hamza
* Copyright 2007 Robert Shearman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -1405,6 +1406,105 @@ HRESULT WINAPI CreateFileMoniker(LPCOLESTR lpszPathName, LPMONIKER * ppmk)
return hr;
}
/* find a character from a set in reverse without the string having to be null-terminated */
static inline WCHAR *memrpbrkW(const WCHAR *ptr, size_t n, const WCHAR *accept)
{
const WCHAR *end, *ret = NULL;
for (end = ptr + n; ptr < end; ptr++) if (strchrW(accept, *ptr)) ret = ptr;
return (WCHAR *)ret;
}
HRESULT FileMoniker_CreateFromDisplayName(LPBC pbc, LPCOLESTR szDisplayName,
LPDWORD pchEaten, LPMONIKER *ppmk)
{
LPCWSTR end;
static const WCHAR wszSeparators[] = {':','\\','/','!',0};
for (end = szDisplayName + strlenW(szDisplayName);
end && (end != szDisplayName);
end = memrpbrkW(szDisplayName, end - szDisplayName, wszSeparators))
{
HRESULT hr;
IRunningObjectTable *rot;
IMoniker *file_moniker;
LPWSTR file_display_name;
LPWSTR full_path_name;
DWORD full_path_name_len;
int len = end - szDisplayName;
file_display_name = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
if (!file_display_name) return E_OUTOFMEMORY;
memcpy(file_display_name, szDisplayName, len * sizeof(WCHAR));
file_display_name[len] = '\0';
hr = CreateFileMoniker(file_display_name, &file_moniker);
if (FAILED(hr))
{
HeapFree(GetProcessHeap(), 0, file_display_name);
return hr;
}
hr = IBindCtx_GetRunningObjectTable(pbc, &rot);
if (FAILED(hr))
{
HeapFree(GetProcessHeap(), 0, file_display_name);
IMoniker_Release(file_moniker);
return hr;
}
hr = IRunningObjectTable_IsRunning(rot, file_moniker);
IRunningObjectTable_Release(rot);
if (FAILED(hr))
{
HeapFree(GetProcessHeap(), 0, file_display_name);
IMoniker_Release(file_moniker);
return hr;
}
if (hr == S_OK)
{
TRACE("found running file moniker for %s\n", debugstr_w(file_display_name));
*pchEaten = len;
*ppmk = file_moniker;
HeapFree(GetProcessHeap(), 0, file_display_name);
return S_OK;
}
full_path_name_len = GetFullPathNameW(file_display_name, 0, NULL, NULL);
if (!full_path_name_len)
{
HeapFree(GetProcessHeap(), 0, file_display_name);
IMoniker_Release(file_moniker);
return MK_E_SYNTAX;
}
full_path_name = HeapAlloc(GetProcessHeap(), 0, full_path_name_len * sizeof(WCHAR));
if (!full_path_name)
{
HeapFree(GetProcessHeap(), 0, file_display_name);
IMoniker_Release(file_moniker);
return E_OUTOFMEMORY;
}
GetFullPathNameW(file_display_name, full_path_name_len, full_path_name, NULL);
if (GetFileAttributesW(full_path_name) == INVALID_FILE_ATTRIBUTES)
TRACE("couldn't open file %s\n", debugstr_w(full_path_name));
else
{
TRACE("got file moniker for %s\n", debugstr_w(szDisplayName));
*pchEaten = len;
*ppmk = file_moniker;
HeapFree(GetProcessHeap(), 0, file_display_name);
HeapFree(GetProcessHeap(), 0, full_path_name);
return S_OK;
}
HeapFree(GetProcessHeap(), 0, file_display_name);
HeapFree(GetProcessHeap(), 0, full_path_name);
IMoniker_Release(file_moniker);
}
return MK_E_CANTOPENFILE;
}
static HRESULT WINAPI FileMonikerCF_QueryInterface(LPCLASSFACTORY iface,
REFIID riid, LPVOID *ppv)
{

View File

@ -4,6 +4,7 @@
* Copyright 1998 Marcus Meissner
* Copyright 1999 Noomen Hamza
* Copyright 2005 Robert Shearman (for CodeWeavers)
* Copyright 2007 Robert Shearman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -43,6 +44,7 @@
#include "wine/unicode.h"
#include "compobj_private.h"
#include "moniker.h"
WINE_DEFAULT_DEBUG_CHANNEL(ole);
@ -826,18 +828,129 @@ GetRunningObjectTable(DWORD reserved, LPRUNNINGOBJECTTABLE *pprot)
return res;
}
static HRESULT get_moniker_for_progid_display_name(LPBC pbc,
LPCOLESTR szDisplayName,
LPDWORD pchEaten,
LPMONIKER *ppmk)
{
CLSID clsid;
HRESULT hr;
LPWSTR progid;
LPCWSTR start = szDisplayName;
LPCWSTR end;
int len;
IMoniker *class_moniker;
if (*start == '@')
start++;
/* find end delimiter */
for (end = start; *end; end++)
if (*end == ':')
break;
len = end - start;
/* must start with '@' or have a ':' somewhere and mustn't be one character
* long (since that looks like an absolute path) */
if (((start == szDisplayName) && (*end == '\0')) || (len <= 1))
return MK_E_SYNTAX;
progid = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
if (progid)
{
memcpy(progid, start, len * sizeof(WCHAR));
progid[len] = '\0';
}
hr = CLSIDFromProgID(progid, &clsid);
HeapFree(GetProcessHeap(), 0, progid);
if (FAILED(hr))
return MK_E_SYNTAX;
hr = CreateClassMoniker(&clsid, &class_moniker);
if (SUCCEEDED(hr))
{
IParseDisplayName *pdn;
hr = IMoniker_BindToObject(class_moniker, pbc, NULL,
&IID_IParseDisplayName, (void **)&pdn);
IMoniker_Release(class_moniker);
if (SUCCEEDED(hr))
{
hr = IParseDisplayName_ParseDisplayName(pdn, pbc,
(LPOLESTR)szDisplayName,
pchEaten, ppmk);
IParseDisplayName_Release(pdn);
}
}
return hr;
}
/******************************************************************************
* MkParseDisplayName [OLE32.@]
*/
HRESULT WINAPI MkParseDisplayName(LPBC pbc, LPCOLESTR szUserName,
HRESULT WINAPI MkParseDisplayName(LPBC pbc, LPCOLESTR szDisplayName,
LPDWORD pchEaten, LPMONIKER *ppmk)
{
FIXME("(%p, %s, %p, %p): stub.\n", pbc, debugstr_w(szUserName), pchEaten, *ppmk);
HRESULT hr = MK_E_SYNTAX;
static const WCHAR wszClsidColon[] = {'c','l','s','i','d',':'};
IMoniker *moniker;
DWORD chEaten;
TRACE("(%p, %s, %p, %p)\n", pbc, debugstr_w(szDisplayName), pchEaten, ppmk);
if (!(IsValidInterface((LPUNKNOWN) pbc)))
return E_INVALIDARG;
return MK_E_SYNTAX;
*pchEaten = 0;
*ppmk = NULL;
if (!strncmpiW(szDisplayName, wszClsidColon, sizeof(wszClsidColon)/sizeof(wszClsidColon[0])))
{
hr = ClassMoniker_CreateFromDisplayName(pbc, szDisplayName, &chEaten, &moniker);
if (FAILED(hr) && (hr != MK_E_SYNTAX))
return hr;
}
else
{
hr = get_moniker_for_progid_display_name(pbc, szDisplayName, &chEaten, &moniker);
if (FAILED(hr) && (hr != MK_E_SYNTAX))
return hr;
}
if (FAILED(hr))
{
hr = FileMoniker_CreateFromDisplayName(pbc, szDisplayName, &chEaten, &moniker);
if (FAILED(hr) && (hr != MK_E_SYNTAX))
return hr;
}
if (SUCCEEDED(hr))
{
while (TRUE)
{
IMoniker *next_moniker;
*pchEaten += chEaten;
szDisplayName += chEaten;
if (!*szDisplayName)
{
*ppmk = moniker;
return S_OK;
}
chEaten = 0;
hr = IMoniker_ParseDisplayName(moniker, pbc, NULL,
(LPOLESTR)szDisplayName, &chEaten,
&next_moniker);
IMoniker_Release(moniker);
if (FAILED(hr))
{
*pchEaten = 0;
break;
}
moniker = next_moniker;
}
}
return hr;
}
/***********************************************************************

View File

@ -35,6 +35,11 @@ HRESULT AntiMonikerCF_Create(REFIID riid, LPVOID *ppv);
HRESULT CompositeMonikerCF_Create(REFIID riid, LPVOID *ppv);
HRESULT ClassMonikerCF_Create(REFIID riid, LPVOID *ppv);
HRESULT FileMoniker_CreateFromDisplayName(LPBC pbc, LPCOLESTR szDisplayName,
LPDWORD pchEaten, LPMONIKER *ppmk);
HRESULT ClassMoniker_CreateFromDisplayName(LPBC pbc, LPCOLESTR szDisplayName,
LPDWORD pchEaten, LPMONIKER *ppmk);
HRESULT MonikerMarshal_Create(IMoniker *inner, IUnknown **outer);

View File

@ -777,12 +777,12 @@ static void test_MkParseDisplayName(void)
ok_ole_success(hr, CreateBindCtx);
hr = MkParseDisplayName(pbc, wszNonExistantProgId, &eaten, &pmk);
todo_wine { ok(hr == MK_E_CANTOPENFILE, "MkParseDisplayName should have failed with MK_E_CANTOPENFILE instead of 0x%08x\n", hr); }
ok(hr == MK_E_CANTOPENFILE, "MkParseDisplayName should have failed with MK_E_CANTOPENFILE instead of 0x%08x\n", hr);
/* no special handling of "clsid:" without the string form of the clsid
* following */
hr = MkParseDisplayName(pbc, wszDisplayNameClsid, &eaten, &pmk);
todo_wine { ok(hr == MK_E_CANTOPENFILE, "MkParseDisplayName should have failed with MK_E_CANTOPENFILE instead of 0x%08x\n", hr); }
ok(hr == MK_E_CANTOPENFILE, "MkParseDisplayName should have failed with MK_E_CANTOPENFILE instead of 0x%08x\n", hr);
/* shows clsid has higher precedence than a running object */
hr = CreateFileMoniker(wszDisplayName, &pmk);
@ -794,7 +794,7 @@ static void test_MkParseDisplayName(void)
IMoniker_Release(pmk);
pmk = NULL;
hr = MkParseDisplayName(pbc, wszDisplayName, &eaten, &pmk);
todo_wine { ok_ole_success(hr, MkParseDisplayName); }
ok_ole_success(hr, MkParseDisplayName);
if (pmk)
{
IMoniker_IsSystemMoniker(pmk, &moniker_type);
@ -814,7 +814,7 @@ static void test_MkParseDisplayName(void)
IMoniker_Release(pmk);
pmk = NULL;
hr = MkParseDisplayName(pbc, wszDisplayNameRunning, &eaten, &pmk);
todo_wine { ok_ole_success(hr, MkParseDisplayName); }
ok_ole_success(hr, MkParseDisplayName);
if (pmk)
{
IMoniker_IsSystemMoniker(pmk, &moniker_type);
@ -830,7 +830,7 @@ static void test_MkParseDisplayName(void)
expected_display_name = wszDisplayNameProgId1;
hr = MkParseDisplayName(pbc, wszDisplayNameProgId1, &eaten, &pmk);
todo_wine { ok_ole_success(hr, MkParseDisplayName); }
ok_ole_success(hr, MkParseDisplayName);
if (pmk)
{
IMoniker_IsSystemMoniker(pmk, &moniker_type);
@ -840,7 +840,7 @@ static void test_MkParseDisplayName(void)
expected_display_name = wszDisplayNameProgId2;
hr = MkParseDisplayName(pbc, wszDisplayNameProgId2, &eaten, &pmk);
todo_wine { ok_ole_success(hr, MkParseDisplayName); }
ok_ole_success(hr, MkParseDisplayName);
if (pmk)
{
IMoniker_IsSystemMoniker(pmk, &moniker_type);
@ -849,7 +849,7 @@ static void test_MkParseDisplayName(void)
}
hr = MkParseDisplayName(pbc, wszDisplayNameProgIdFail, &eaten, &pmk);
todo_wine { ok(hr == MK_E_CANTOPENFILE, "MkParseDisplayName with ProgId without marker should fail with MK_E_CANTOPENFILE instead of 0x%08x\n", hr); }
ok(hr == MK_E_CANTOPENFILE, "MkParseDisplayName with ProgId without marker should fail with MK_E_CANTOPENFILE instead of 0x%08x\n", hr);
hr = CoRevokeClassObject(pdwReg1);
ok_ole_success(hr, CoRevokeClassObject);
@ -858,7 +858,7 @@ static void test_MkParseDisplayName(void)
strcat(szDisplayNameFile, "\\kernel32.dll");
MultiByteToWideChar(CP_ACP, 0, szDisplayNameFile, -1, wszDisplayNameFile, sizeof(wszDisplayNameFile)/sizeof(wszDisplayNameFile[0]));
hr = MkParseDisplayName(pbc, wszDisplayNameFile, &eaten, &pmk);
todo_wine { ok_ole_success(hr, MkParseDisplayName); }
ok_ole_success(hr, MkParseDisplayName);
if (pmk)
{
IMoniker_IsSystemMoniker(pmk, &moniker_type);
@ -867,7 +867,7 @@ static void test_MkParseDisplayName(void)
}
hr = MkParseDisplayName(pbc, wszDisplayName, &eaten, &pmk);
todo_wine { ok_ole_success(hr, MkParseDisplayName); }
ok_ole_success(hr, MkParseDisplayName);
if (pmk)
{