📄 shellpath.c
字号:
/*
* Unit tests for shell32 SHGet{Special}Folder{Path|Location} functions.
*
* Copyright 2004 Juan Lang
*
* 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
* This is a test program for the SHGet{Special}Folder{Path|Location} functions
* of shell32, that get either a filesytem path or a LPITEMIDLIST (shell
* namespace) path for a given folder (CSIDL value).
*
* FIXME:
* - Need to verify on more systems.
*/
#define COBJMACROS
#include <stdarg.h>
#include <stdio.h>
#include "windef.h"
#include "winbase.h"
#include "initguid.h"
#include "shlguid.h"
#include "shlobj.h"
#include "shlwapi.h"
#include "wine/test.h"
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(x) ( sizeof(x) / sizeof((x)[0]) )
#endif
/* from pidl.h, not included here: */
#ifndef PT_GUID
#define PT_GUID 0x1f /* no path */
#endif
#ifndef PT_DRIVE
#define PT_DRIVE 0x23 /* has path */
#endif
#ifndef PT_DRIVE2
#define PT_DRIVE2 0x25 /* has path */
#endif
#ifndef PT_SHELLEXT
#define PT_SHELLEXT 0x2e /* no path */
#endif
#ifndef PT_FOLDER
#define PT_FOLDER 0x31 /* has path */
#endif
#ifndef PT_WORKGRP
#define PT_WORKGRP 0x41 /* no path */
#endif
#ifndef PT_YAGUID
#define PT_YAGUID 0x70 /* no path */
#endif
/* FIXME: this is used for history/favorites folders; what's a better name? */
#ifndef PT_IESPECIAL2
#define PT_IESPECIAL2 0xb1 /* has path */
#endif
static GUID CLSID_CommonDocuments = { 0x0000000c, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x1a } };
struct shellExpectedValues {
int folder;
BYTE pidlType;
};
static HMODULE hShell32;
static HRESULT (WINAPI *pSHGetFolderPathA)(HWND, int, HANDLE, DWORD, LPSTR);
static HRESULT (WINAPI *pSHGetFolderLocation)(HWND, int, HANDLE, DWORD,
LPITEMIDLIST *);
static BOOL (WINAPI *pSHGetSpecialFolderPathA)(HWND, LPSTR, int, BOOL);
static HRESULT (WINAPI *pSHGetSpecialFolderLocation)(HWND, int, LPITEMIDLIST *);
static LPITEMIDLIST (WINAPI *pILFindLastID)(LPCITEMIDLIST);
static int (WINAPI *pSHFileOperationA)(LPSHFILEOPSTRUCTA);
static HRESULT (WINAPI *pSHGetMalloc)(LPMALLOC *);
static DLLVERSIONINFO shellVersion = { 0 };
static LPMALLOC pMalloc;
static const struct shellExpectedValues requiredShellValues[] = {
{ CSIDL_BITBUCKET, PT_GUID },
{ CSIDL_CONTROLS, PT_SHELLEXT },
{ CSIDL_COOKIES, PT_FOLDER },
{ CSIDL_DESKTOPDIRECTORY, PT_FOLDER },
{ CSIDL_DRIVES, PT_GUID },
{ CSIDL_FAVORITES, PT_FOLDER },
{ CSIDL_FONTS, PT_FOLDER },
/* FIXME: the following fails in Wine, returns type PT_FOLDER
{ CSIDL_HISTORY, PT_IESPECIAL2 },
*/
{ CSIDL_INTERNET, PT_GUID },
{ CSIDL_NETHOOD, PT_FOLDER },
{ CSIDL_NETWORK, PT_GUID },
{ CSIDL_PRINTERS, PT_YAGUID },
{ CSIDL_PRINTHOOD, PT_FOLDER },
{ CSIDL_PROGRAMS, PT_FOLDER },
{ CSIDL_RECENT, PT_FOLDER },
{ CSIDL_SENDTO, PT_FOLDER },
{ CSIDL_STARTMENU, PT_FOLDER },
{ CSIDL_STARTUP, PT_FOLDER },
{ CSIDL_TEMPLATES, PT_FOLDER },
};
static const struct shellExpectedValues optionalShellValues[] = {
/* FIXME: the following only semi-succeed; they return NULL PIDLs on XP.. hmm.
{ CSIDL_ALTSTARTUP, PT_FOLDER },
{ CSIDL_COMMON_ALTSTARTUP, PT_FOLDER },
{ CSIDL_COMMON_OEM_LINKS, PT_FOLDER },
*/
/* Windows NT-only: */
{ CSIDL_COMMON_DESKTOPDIRECTORY, PT_FOLDER },
{ CSIDL_COMMON_DOCUMENTS, PT_SHELLEXT },
{ CSIDL_COMMON_FAVORITES, PT_FOLDER },
{ CSIDL_COMMON_PROGRAMS, PT_FOLDER },
{ CSIDL_COMMON_STARTMENU, PT_FOLDER },
{ CSIDL_COMMON_STARTUP, PT_FOLDER },
{ CSIDL_COMMON_TEMPLATES, PT_FOLDER },
/* first appearing in shell32 version 4.71: */
{ CSIDL_APPDATA, PT_FOLDER },
/* first appearing in shell32 version 4.72: */
{ CSIDL_INTERNET_CACHE, PT_IESPECIAL2 },
/* first appearing in shell32 version 5.0: */
{ CSIDL_ADMINTOOLS, PT_FOLDER },
{ CSIDL_COMMON_APPDATA, PT_FOLDER },
{ CSIDL_LOCAL_APPDATA, PT_FOLDER },
{ CSIDL_MYDOCUMENTS, PT_FOLDER },
{ CSIDL_MYMUSIC, PT_FOLDER },
{ CSIDL_MYPICTURES, PT_FOLDER },
{ CSIDL_MYVIDEO, PT_FOLDER },
{ CSIDL_PROFILE, PT_FOLDER },
{ CSIDL_PROGRAM_FILES, PT_FOLDER },
{ CSIDL_PROGRAM_FILESX86, PT_FOLDER },
{ CSIDL_PROGRAM_FILES_COMMON, PT_FOLDER },
{ CSIDL_PROGRAM_FILES_COMMONX86, PT_FOLDER },
{ CSIDL_SYSTEM, PT_FOLDER },
{ CSIDL_WINDOWS, PT_FOLDER },
/* first appearing in shell32 6.0: */
{ CSIDL_CDBURN_AREA, PT_FOLDER },
{ CSIDL_COMMON_MUSIC, PT_FOLDER },
{ CSIDL_COMMON_PICTURES, PT_FOLDER },
{ CSIDL_COMMON_VIDEO, PT_FOLDER },
{ CSIDL_COMPUTERSNEARME, PT_WORKGRP },
{ CSIDL_RESOURCES, PT_FOLDER },
{ CSIDL_RESOURCES_LOCALIZED, PT_FOLDER },
};
static void loadShell32(void)
{
hShell32 = LoadLibraryA("shell32");
if (hShell32)
{
HRESULT (WINAPI *pDllGetVersion)(DLLVERSIONINFO *);
pSHGetFolderPathA = (void *)GetProcAddress(hShell32,
"SHGetFolderPathA");
pSHGetFolderLocation = (void *)GetProcAddress(hShell32,
"SHGetFolderLocation");
pSHGetSpecialFolderPathA = (void *)GetProcAddress(hShell32,
"SHGetSpecialFolderPathA");
pSHGetSpecialFolderLocation = (void *)GetProcAddress(hShell32,
"SHGetSpecialFolderLocation");
pDllGetVersion = (void *)GetProcAddress(hShell32, "DllGetVersion");
pILFindLastID = (void *)GetProcAddress(hShell32, "ILFindLastID");
if (!pILFindLastID)
pILFindLastID = (void *)GetProcAddress(hShell32, (LPCSTR)16);
pSHFileOperationA = (void *)GetProcAddress(hShell32,
"SHFileOperationA");
pSHGetMalloc = (void *)GetProcAddress(hShell32, "SHGetMalloc");
ok(pSHGetMalloc != NULL, "shell32 is missing SHGetMalloc\n");
if (pSHGetMalloc)
{
HRESULT hr = pSHGetMalloc(&pMalloc);
ok(SUCCEEDED(hr), "SHGetMalloc failed: 0x%08lx\n", hr);
ok(pMalloc != NULL, "SHGetMalloc returned a NULL IMalloc\n");
}
if (pDllGetVersion)
{
shellVersion.cbSize = sizeof(shellVersion);
pDllGetVersion(&shellVersion);
if (winetest_interactive)
printf("shell32 version is %ld.%ld\n",
shellVersion.dwMajorVersion, shellVersion.dwMinorVersion);
}
}
}
#ifndef CSIDL_PROFILES
#define CSIDL_PROFILES 0x003e
#endif
/* A couple utility printing functions */
static const char *getFolderName(int folder)
{
static char unknown[17];
#define CSIDL_TO_STR(x) case x: return#x;
switch (folder)
{
CSIDL_TO_STR(CSIDL_DESKTOP);
CSIDL_TO_STR(CSIDL_INTERNET);
CSIDL_TO_STR(CSIDL_PROGRAMS);
CSIDL_TO_STR(CSIDL_CONTROLS);
CSIDL_TO_STR(CSIDL_PRINTERS);
CSIDL_TO_STR(CSIDL_PERSONAL);
CSIDL_TO_STR(CSIDL_FAVORITES);
CSIDL_TO_STR(CSIDL_STARTUP);
CSIDL_TO_STR(CSIDL_RECENT);
CSIDL_TO_STR(CSIDL_SENDTO);
CSIDL_TO_STR(CSIDL_BITBUCKET);
CSIDL_TO_STR(CSIDL_STARTMENU);
CSIDL_TO_STR(CSIDL_MYDOCUMENTS);
CSIDL_TO_STR(CSIDL_MYMUSIC);
CSIDL_TO_STR(CSIDL_MYVIDEO);
CSIDL_TO_STR(CSIDL_DESKTOPDIRECTORY);
CSIDL_TO_STR(CSIDL_DRIVES);
CSIDL_TO_STR(CSIDL_NETWORK);
CSIDL_TO_STR(CSIDL_NETHOOD);
CSIDL_TO_STR(CSIDL_FONTS);
CSIDL_TO_STR(CSIDL_TEMPLATES);
CSIDL_TO_STR(CSIDL_COMMON_STARTMENU);
CSIDL_TO_STR(CSIDL_COMMON_PROGRAMS);
CSIDL_TO_STR(CSIDL_COMMON_STARTUP);
CSIDL_TO_STR(CSIDL_COMMON_DESKTOPDIRECTORY);
CSIDL_TO_STR(CSIDL_APPDATA);
CSIDL_TO_STR(CSIDL_PRINTHOOD);
CSIDL_TO_STR(CSIDL_LOCAL_APPDATA);
CSIDL_TO_STR(CSIDL_ALTSTARTUP);
CSIDL_TO_STR(CSIDL_COMMON_ALTSTARTUP);
CSIDL_TO_STR(CSIDL_COMMON_FAVORITES);
CSIDL_TO_STR(CSIDL_INTERNET_CACHE);
CSIDL_TO_STR(CSIDL_COOKIES);
CSIDL_TO_STR(CSIDL_HISTORY);
CSIDL_TO_STR(CSIDL_COMMON_APPDATA);
CSIDL_TO_STR(CSIDL_WINDOWS);
CSIDL_TO_STR(CSIDL_SYSTEM);
CSIDL_TO_STR(CSIDL_PROGRAM_FILES);
CSIDL_TO_STR(CSIDL_MYPICTURES);
CSIDL_TO_STR(CSIDL_PROFILE);
CSIDL_TO_STR(CSIDL_SYSTEMX86);
CSIDL_TO_STR(CSIDL_PROGRAM_FILESX86);
CSIDL_TO_STR(CSIDL_PROGRAM_FILES_COMMON);
CSIDL_TO_STR(CSIDL_PROGRAM_FILES_COMMONX86);
CSIDL_TO_STR(CSIDL_COMMON_TEMPLATES);
CSIDL_TO_STR(CSIDL_COMMON_DOCUMENTS);
CSIDL_TO_STR(CSIDL_COMMON_ADMINTOOLS);
CSIDL_TO_STR(CSIDL_ADMINTOOLS);
CSIDL_TO_STR(CSIDL_CONNECTIONS);
CSIDL_TO_STR(CSIDL_PROFILES);
CSIDL_TO_STR(CSIDL_COMMON_MUSIC);
CSIDL_TO_STR(CSIDL_COMMON_PICTURES);
CSIDL_TO_STR(CSIDL_COMMON_VIDEO);
CSIDL_TO_STR(CSIDL_RESOURCES);
CSIDL_TO_STR(CSIDL_RESOURCES_LOCALIZED);
CSIDL_TO_STR(CSIDL_COMMON_OEM_LINKS);
CSIDL_TO_STR(CSIDL_CDBURN_AREA);
CSIDL_TO_STR(CSIDL_COMPUTERSNEARME);
#undef CSIDL_TO_STR
default:
wnsprintfA(unknown, sizeof(unknown), "unknown (0x%04x)", folder);
return unknown;
}
}
static const char *printGUID(const GUID *guid)
{
static char guidSTR[39];
if (!guid) return NULL;
wnsprintfA(guidSTR, sizeof(guidSTR),
"{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
guid->Data1, guid->Data2, guid->Data3,
guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
return guidSTR;
}
static void testSHGetFolderLocationInvalidArgs(void)
{
LPITEMIDLIST pidl;
HRESULT hr;
if (!pSHGetFolderLocation) return;
/* check a bogus CSIDL: */
pidl = NULL;
hr = pSHGetFolderLocation(NULL, 0xeeee, NULL, 0, &pidl);
ok(hr == E_INVALIDARG,
"SHGetFolderLocation(NULL, 0xeeee, NULL, 0, &pidl)\n"
"returned 0x%08lx, expected E_INVALIDARG\n", hr);
if (SUCCEEDED(hr))
IMalloc_Free(pMalloc, pidl);
/* check a bogus user token: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -