Added initial tests for shdocvw's FolderShortcut related

functionality.
oldstable
Michael Jung 2005-10-31 14:13:14 +00:00 committed by Alexandre Julliard
parent 98ed5585c7
commit 7a48f838dd
6 changed files with 236 additions and 1 deletions

3
configure vendored

File diff suppressed because one or more lines are too long

View File

@ -1654,6 +1654,7 @@ dlls/serialui/Makefile
dlls/setupapi/Makefile
dlls/setupapi/tests/Makefile
dlls/shdocvw/Makefile
dlls/shdocvw/tests/Makefile
dlls/shell32/Makefile
dlls/shell32/tests/Makefile
dlls/shfolder/Makefile

View File

@ -21,6 +21,8 @@ C_SRCS = \
RC_SRCS = shdocvw.rc
SUBDIRS = tests
@MAKE_DLL_RULES@
### Dependencies:

View File

@ -0,0 +1,3 @@
Makefile
shortcut.ok
testlist.c

View File

@ -0,0 +1,14 @@
TOPSRCDIR = @top_srcdir@
TOPOBJDIR = ../../..
SRCDIR = @srcdir@
VPATH = @srcdir@
TESTDLL = shdocvw.dll
IMPORTS = shell32 ole32 advapi32 kernel32
EXTRALIBS = -luuid
CTESTS = \
shortcut.c
@MAKE_TEST_RULES@
### Dependencies:

View File

@ -0,0 +1,214 @@
/*
* Unit tests to document shdocvw's CLSID_FolderShortcut related functionality
*
* Copyright 2005 Michael Jung
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* At least since Windows 2000 it's possible to add FolderShortcut objects
* by creating some registry entries. Those objects, which refer to some
* point in the filesystem, can be registered in the shell namespace like other
* shell namespace extensions. Icons, names and filesystem location can be
* configured. This is documented at http://www.virtualplastic.net/html/ui_shell.html
* You can also google for a tool called "ShellObjectEditor" by "Tropical
* Technologies". This mechanism would be cool for wine, since we could
* map Gnome's virtual devices to FolderShortcuts and have them appear in the
* file dialogs. These unit tests are meant to document how this mechanism
* works on windows. */
#include <stdarg.h>
#define COBJMACROS
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "shlobj.h"
#include "shobjidl.h"
#include "shlguid.h"
#include "ole2.h"
#include "wine/unicode.h"
#include "wine/test.h"
/* The following definitions and helper functions are meant to make the de-/registration
* of the various necessary registry keys easier. */
struct registry_value {
const char *szName;
const DWORD dwType;
const char *szValue;
const DWORD dwValue;
};
#define REG_VALUE_ADDR(x) ((x->dwType==REG_SZ)?(const BYTE *)x->szValue:(const BYTE *)&x->dwValue)
#define REG_VALUE_SIZE(x) ((x->dwType==REG_SZ)?strlen(x->szValue)+1:sizeof(DWORD))
struct registry_key {
const char *szName;
const struct registry_value *pValues;
const unsigned int cValues;
const struct registry_key *pSubKeys;
const unsigned int cSubKeys;
};
static const struct registry_value ShellFolder_values[] = {
{ "WantsFORPARSING", REG_SZ, "", 0 },
{ "Attributes", REG_DWORD, NULL, 0xF8000100 }
};
static const struct registry_value Instance_values[] = {
{ "CLSID", REG_SZ, "{0AFACED1-E828-11D1-9187-B532F1E9575D}", 0 }
};
static const struct registry_value InitPropertyBag_values[] = {
{ "Attributes", REG_DWORD, NULL, 0x00000015 },
{ "Target", REG_SZ, "C:\\", 0 }
};
static const struct registry_key Instance_keys[] = {
{ "InitPropertyBag", InitPropertyBag_values, 2, NULL, 0 }
};
static const struct registry_value InProcServer32_values[] = {
{ NULL, REG_SZ, "shdocvw.dll", 0 },
{ "ThreadingModel", REG_SZ, "Apartment", 0 }
};
static const struct registry_value DefaultIcon_values[] = {
{ NULL, REG_SZ,"shell32.dll,8", 0 }
};
static const struct registry_key ShortcutCLSID_keys[] = {
{ "DefaultIcon", DefaultIcon_values, 1, NULL, 0 },
{ "InProcServer32", InProcServer32_values, 2, NULL, 0 },
{ "Instance", Instance_values, 1, Instance_keys, 1 },
{ "ShellFolder", ShellFolder_values, 2, NULL, 0 }
};
static const struct registry_value ShortcutCLSID_values[] = {
{ NULL, REG_SZ, "WineTest", 0 }
};
static const struct registry_key HKEY_CLASSES_ROOT_keys[] = {
{ "CLSID\\{9B352EBF-2765-45C1-B4C6-85CC7F7ABC64}", ShortcutCLSID_values, 1, ShortcutCLSID_keys, 4}
};
/* register_keys - helper function, which recursively creates the registry keys and values in
* parameter 'keys' in the registry under hRootKey. */
static BOOL register_keys(HKEY hRootKey, const struct registry_key *keys, unsigned int numKeys) {
HKEY hKey;
unsigned int iKey, iValue;
for (iKey = 0; iKey < numKeys; iKey++) {
if (ERROR_SUCCESS == RegCreateKeyExA(hRootKey, keys[iKey].szName, 0, NULL, 0,
KEY_WRITE, NULL, &hKey, NULL))
{
for (iValue = 0; iValue < keys[iKey].cValues; iValue++) {
const struct registry_value * value = &keys[iKey].pValues[iValue];
if (ERROR_SUCCESS != RegSetValueExA(hKey, value->szName, 0, value->dwType,
REG_VALUE_ADDR(value), REG_VALUE_SIZE(value)))
{
RegCloseKey(hKey);
return FALSE;
}
}
if (!register_keys(hKey, keys[iKey].pSubKeys, keys[iKey].cSubKeys)) {
RegCloseKey(hKey);
return FALSE;
}
RegCloseKey(hKey);
}
}
return TRUE;
}
/* unregister_keys - clean up after register_keys */
static void unregister_keys(HKEY hRootKey, const struct registry_key *keys, unsigned int numKeys) {
HKEY hKey;
unsigned int iKey;
for (iKey = 0; iKey < numKeys; iKey++) {
if (ERROR_SUCCESS == RegOpenKeyExA(hRootKey, keys[iKey].szName, 0, DELETE, &hKey)) {
unregister_keys(hKey, keys[iKey].pSubKeys, keys[iKey].cSubKeys);
RegCloseKey(hKey);
}
RegDeleteKeyA(hRootKey, keys[iKey].szName);
}
}
static void test_ShortcutFolder() {
LPSHELLFOLDER pDesktopFolder, pWineTestFolder;
IPersist *pWineTestPersist;
LPITEMIDLIST pidlWineTestFolder;
HRESULT hr;
CLSID clsid;
WCHAR wszWineTestFolder[] = {
':',':','{','9','B','3','5','2','E','B','F','-','2','7','6','5','-','4','5','C','1','-',
'B','4','C','6','-','8','5','C','C','7','F','7','A','B','C','6','4','}',0 };
/* First, we register all the necessary registry keys/values for our 'WineTest'
* shell object. */
register_keys(HKEY_CLASSES_ROOT, HKEY_CLASSES_ROOT_keys, 1);
hr = SHGetDesktopFolder(&pDesktopFolder);
ok (SUCCEEDED(hr), "SHGetDesktopFolder failed! hr = %08lx\n", hr);
if (FAILED(hr)) goto cleanup;
/* Convert the wszWineTestFolder string to an ITEMIDLIST. */
hr = IShellFolder_ParseDisplayName(pDesktopFolder, NULL, NULL, wszWineTestFolder, NULL,
&pidlWineTestFolder, NULL);
ok (SUCCEEDED(hr), "IShellFolder::ParseDisplayName failed! hr = %08lx\n", hr);
if (FAILED(hr)) {
IShellFolder_Release(pDesktopFolder);
goto cleanup;
}
/* Bind to a WineTest folder object. There has to be some support for this in shdocvw.dll.
* This isn't implemented in wine yet.*/
hr = IShellFolder_BindToObject(pDesktopFolder, pidlWineTestFolder, NULL, &IID_IShellFolder,
(LPVOID*)&pWineTestFolder);
IShellFolder_Release(pDesktopFolder);
ILFree(pidlWineTestFolder);
todo_wine { ok (SUCCEEDED(hr), "IShellFolder::BindToObject(WineTestFolder) failed! hr = %08lx\n", hr); }
if (FAILED(hr)) goto cleanup;
hr = IShellFolder_QueryInterface(pWineTestFolder, &IID_IPersist, (LPVOID*)&pWineTestPersist);
ok (SUCCEEDED(hr), "IShellFolder::QueryInterface(IPersist) failed! hr = %08lx\n", hr);
IShellFolder_Release(pWineTestFolder);
if (FAILED(hr)) goto cleanup;
/* The resulting folder object has the FolderShortcut CLSID, instead of it's own. */
hr = IPersist_GetClassID(pWineTestPersist, &clsid);
ok (SUCCEEDED(hr), "IPersist::GetClassID failed! hr = %08lx\n", hr);
ok (IsEqualCLSID(&CLSID_FolderShortcut, &clsid), "GetClassId returned wrong CLSID!\n");
IPersist_Release(pWineTestPersist);
cleanup:
unregister_keys(HKEY_CLASSES_ROOT, HKEY_CLASSES_ROOT_keys, 1);
}
START_TEST(shortcut)
{
OleInitialize(NULL);
test_ShortcutFolder();
OleUninitialize();
}