1 /* 2 * Unit tests for shell32 SHGet{Special}Folder{Path|Location} functions. 3 * 4 * Copyright 2004 Juan Lang 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 * This is a test program for the SHGet{Special}Folder{Path|Location} functions 20 * of shell32, that get either a filesystem path or a LPITEMIDLIST (shell 21 * namespace) path for a given folder (CSIDL value). 22 */ 23 24 #define COBJMACROS 25 26 #include <stdarg.h> 27 #include <stdio.h> 28 #include "windef.h" 29 #include "winbase.h" 30 #include "shlguid.h" 31 #include "shlobj.h" 32 #include "shlwapi.h" 33 #include "knownfolders.h" 34 #include "shellapi.h" 35 #include "wine/test.h" 36 37 #include "initguid.h" 38 39 /* CSIDL_MYDOCUMENTS is now the same as CSIDL_PERSONAL, but what we want 40 * here is its original value. 41 */ 42 #define OLD_CSIDL_MYDOCUMENTS 0x000c 43 44 DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0); 45 46 /* from pidl.h, not included here: */ 47 #ifndef PT_CPL /* Guess, Win7 uses this for CSIDL_CONTROLS */ 48 #define PT_CPL 0x01 /* no path */ 49 #endif 50 #ifndef PT_GUID 51 #define PT_GUID 0x1f /* no path */ 52 #endif 53 #ifndef PT_DRIVE 54 #define PT_DRIVE 0x23 /* has path */ 55 #endif 56 #ifndef PT_DRIVE2 57 #define PT_DRIVE2 0x25 /* has path */ 58 #endif 59 #ifndef PT_SHELLEXT 60 #define PT_SHELLEXT 0x2e /* no path */ 61 #endif 62 #ifndef PT_FOLDER 63 #define PT_FOLDER 0x31 /* has path */ 64 #endif 65 #ifndef PT_FOLDERW 66 #define PT_FOLDERW 0x35 /* has path */ 67 #endif 68 #ifndef PT_WORKGRP 69 #define PT_WORKGRP 0x41 /* no path */ 70 #endif 71 #ifndef PT_YAGUID 72 #define PT_YAGUID 0x70 /* no path */ 73 #endif 74 /* FIXME: this is used for history/favorites folders; what's a better name? */ 75 #ifndef PT_IESPECIAL2 76 #define PT_IESPECIAL2 0xb1 /* has path */ 77 #endif 78 79 static GUID CLSID_CommonDocuments = { 0x0000000c, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x1a } }; 80 81 struct shellExpectedValues { 82 int folder; 83 int numTypes; 84 const BYTE *types; 85 }; 86 87 static HRESULT (WINAPI *pDllGetVersion)(DLLVERSIONINFO *); 88 static HRESULT (WINAPI *pSHGetFolderPathA)(HWND, int, HANDLE, DWORD, LPSTR); 89 static HRESULT (WINAPI *pSHGetFolderLocation)(HWND, int, HANDLE, DWORD, 90 LPITEMIDLIST *); 91 static BOOL (WINAPI *pSHGetSpecialFolderPathA)(HWND, LPSTR, int, BOOL); 92 static HRESULT (WINAPI *pSHGetSpecialFolderLocation)(HWND, int, LPITEMIDLIST *); 93 static LPITEMIDLIST (WINAPI *pILFindLastID)(LPCITEMIDLIST); 94 static int (WINAPI *pSHFileOperationA)(LPSHFILEOPSTRUCTA); 95 static HRESULT (WINAPI *pSHGetMalloc)(LPMALLOC *); 96 static UINT (WINAPI *pGetSystemWow64DirectoryA)(LPSTR,UINT); 97 static HRESULT (WINAPI *pSHGetKnownFolderPath)(REFKNOWNFOLDERID, DWORD, HANDLE, PWSTR *); 98 static HRESULT (WINAPI *pSHSetKnownFolderPath)(REFKNOWNFOLDERID, DWORD, HANDLE, PWSTR); 99 static HRESULT (WINAPI *pSHGetFolderPathEx)(REFKNOWNFOLDERID, DWORD, HANDLE, LPWSTR, DWORD); 100 static BOOL (WINAPI *pPathYetAnotherMakeUniqueName)(PWSTR, PCWSTR, PCWSTR, PCWSTR); 101 static HRESULT (WINAPI *pSHGetKnownFolderIDList)(REFKNOWNFOLDERID, DWORD, HANDLE, PIDLIST_ABSOLUTE*); 102 103 static DLLVERSIONINFO shellVersion = { 0 }; 104 static LPMALLOC pMalloc; 105 static const BYTE guidType[] = { PT_GUID }; 106 static const BYTE controlPanelType[] = { PT_SHELLEXT, PT_GUID, PT_CPL }; 107 static const BYTE folderType[] = { PT_FOLDER, PT_FOLDERW }; 108 static const BYTE favoritesType[] = { PT_FOLDER, PT_FOLDERW, 0, PT_IESPECIAL2 /* Win98 */ }; 109 static const BYTE folderOrSpecialType[] = { PT_FOLDER, PT_IESPECIAL2 }; 110 static const BYTE personalType[] = { PT_FOLDER, PT_GUID, PT_DRIVE, 0xff /* Win9x */, 111 PT_IESPECIAL2 /* Win98 */, 0 /* Vista */, PT_SHELLEXT /* win8 */ }; 112 /* FIXME: don't know the type of 0x71 returned by Vista/2008 for printers */ 113 static const BYTE printersType[] = { PT_YAGUID, PT_SHELLEXT, 0x71 }; 114 static const BYTE ieSpecialType[] = { PT_IESPECIAL2 }; 115 static const BYTE shellExtType[] = { PT_SHELLEXT }; 116 static const BYTE workgroupType[] = { PT_WORKGRP }; 117 #define DECLARE_TYPE(x, y) { x, ARRAY_SIZE(y), y } 118 static const struct shellExpectedValues requiredShellValues[] = { 119 DECLARE_TYPE(CSIDL_BITBUCKET, guidType), 120 DECLARE_TYPE(CSIDL_CONTROLS, controlPanelType), 121 DECLARE_TYPE(CSIDL_COOKIES, folderType), 122 DECLARE_TYPE(CSIDL_DESKTOPDIRECTORY, folderType), 123 DECLARE_TYPE(CSIDL_DRIVES, guidType), 124 DECLARE_TYPE(CSIDL_FAVORITES, favoritesType), 125 DECLARE_TYPE(CSIDL_FONTS, folderOrSpecialType), 126 /* FIXME: the following fails in Wine, returns type PT_FOLDER 127 DECLARE_TYPE(CSIDL_HISTORY, ieSpecialType), 128 */ 129 DECLARE_TYPE(CSIDL_INTERNET, guidType), 130 DECLARE_TYPE(CSIDL_NETHOOD, folderType), 131 DECLARE_TYPE(CSIDL_NETWORK, guidType), 132 DECLARE_TYPE(CSIDL_PERSONAL, personalType), 133 DECLARE_TYPE(CSIDL_PRINTERS, printersType), 134 DECLARE_TYPE(CSIDL_PRINTHOOD, folderType), 135 DECLARE_TYPE(CSIDL_PROGRAMS, folderType), 136 DECLARE_TYPE(CSIDL_RECENT, folderOrSpecialType), 137 DECLARE_TYPE(CSIDL_SENDTO, folderType), 138 DECLARE_TYPE(CSIDL_STARTMENU, folderType), 139 DECLARE_TYPE(CSIDL_STARTUP, folderType), 140 DECLARE_TYPE(CSIDL_TEMPLATES, folderType), 141 }; 142 static const struct shellExpectedValues optionalShellValues[] = { 143 /* FIXME: the following only semi-succeed; they return NULL PIDLs on XP.. hmm. 144 DECLARE_TYPE(CSIDL_ALTSTARTUP, folderType), 145 DECLARE_TYPE(CSIDL_COMMON_ALTSTARTUP, folderType), 146 DECLARE_TYPE(CSIDL_COMMON_OEM_LINKS, folderType), 147 */ 148 /* Windows NT-only: */ 149 DECLARE_TYPE(CSIDL_COMMON_DESKTOPDIRECTORY, folderType), 150 DECLARE_TYPE(CSIDL_COMMON_DOCUMENTS, shellExtType), 151 DECLARE_TYPE(CSIDL_COMMON_FAVORITES, folderType), 152 DECLARE_TYPE(CSIDL_COMMON_PROGRAMS, folderType), 153 DECLARE_TYPE(CSIDL_COMMON_STARTMENU, folderType), 154 DECLARE_TYPE(CSIDL_COMMON_STARTUP, folderType), 155 DECLARE_TYPE(CSIDL_COMMON_TEMPLATES, folderType), 156 /* first appearing in shell32 version 4.71: */ 157 DECLARE_TYPE(CSIDL_APPDATA, folderType), 158 /* first appearing in shell32 version 4.72: */ 159 DECLARE_TYPE(CSIDL_INTERNET_CACHE, ieSpecialType), 160 /* first appearing in shell32 version 5.0: */ 161 DECLARE_TYPE(CSIDL_ADMINTOOLS, folderType), 162 DECLARE_TYPE(CSIDL_COMMON_APPDATA, folderType), 163 DECLARE_TYPE(CSIDL_LOCAL_APPDATA, folderType), 164 DECLARE_TYPE(OLD_CSIDL_MYDOCUMENTS, folderType), 165 DECLARE_TYPE(CSIDL_MYMUSIC, folderType), 166 DECLARE_TYPE(CSIDL_MYPICTURES, folderType), 167 DECLARE_TYPE(CSIDL_MYVIDEO, folderType), 168 DECLARE_TYPE(CSIDL_PROFILE, folderType), 169 DECLARE_TYPE(CSIDL_PROGRAM_FILES, folderType), 170 DECLARE_TYPE(CSIDL_PROGRAM_FILESX86, folderType), 171 DECLARE_TYPE(CSIDL_PROGRAM_FILES_COMMON, folderType), 172 DECLARE_TYPE(CSIDL_PROGRAM_FILES_COMMONX86, folderType), 173 DECLARE_TYPE(CSIDL_SYSTEM, folderType), 174 DECLARE_TYPE(CSIDL_WINDOWS, folderType), 175 /* first appearing in shell32 6.0: */ 176 DECLARE_TYPE(CSIDL_CDBURN_AREA, folderType), 177 DECLARE_TYPE(CSIDL_COMMON_MUSIC, folderType), 178 DECLARE_TYPE(CSIDL_COMMON_PICTURES, folderType), 179 DECLARE_TYPE(CSIDL_COMMON_VIDEO, folderType), 180 DECLARE_TYPE(CSIDL_COMPUTERSNEARME, workgroupType), 181 DECLARE_TYPE(CSIDL_RESOURCES, folderType), 182 DECLARE_TYPE(CSIDL_RESOURCES_LOCALIZED, folderType), 183 }; 184 #undef DECLARE_TYPE 185 186 static void loadShell32(void) 187 { 188 HMODULE hShell32 = GetModuleHandleA("shell32"); 189 190 #define GET_PROC(func) \ 191 p ## func = (void*)GetProcAddress(hShell32, #func); \ 192 if(!p ## func) \ 193 trace("GetProcAddress(%s) failed\n", #func); 194 195 GET_PROC(DllGetVersion) 196 GET_PROC(SHGetFolderPathA) 197 GET_PROC(SHGetFolderPathEx) 198 GET_PROC(SHGetFolderLocation) 199 GET_PROC(SHGetKnownFolderPath) 200 GET_PROC(SHSetKnownFolderPath) 201 GET_PROC(SHGetSpecialFolderPathA) 202 GET_PROC(SHGetSpecialFolderLocation) 203 GET_PROC(ILFindLastID) 204 if (!pILFindLastID) 205 pILFindLastID = (void *)GetProcAddress(hShell32, (LPCSTR)16); 206 GET_PROC(SHFileOperationA) 207 GET_PROC(SHGetMalloc) 208 GET_PROC(PathYetAnotherMakeUniqueName) 209 GET_PROC(SHGetKnownFolderIDList) 210 211 ok(pSHGetMalloc != NULL, "shell32 is missing SHGetMalloc\n"); 212 if (pSHGetMalloc) 213 { 214 HRESULT hr = pSHGetMalloc(&pMalloc); 215 216 ok(hr == S_OK, "SHGetMalloc failed: 0x%08x\n", hr); 217 ok(pMalloc != NULL, "SHGetMalloc returned a NULL IMalloc\n"); 218 } 219 220 if (pDllGetVersion) 221 { 222 shellVersion.cbSize = sizeof(shellVersion); 223 pDllGetVersion(&shellVersion); 224 trace("shell32 version is %d.%d\n", 225 shellVersion.dwMajorVersion, shellVersion.dwMinorVersion); 226 } 227 #undef GET_PROC 228 } 229 230 #ifndef CSIDL_PROFILES 231 #define CSIDL_PROFILES 0x003e 232 #endif 233 234 /* A couple utility printing functions */ 235 static const char *getFolderName(int folder) 236 { 237 static char unknown[32]; 238 239 #define CSIDL_TO_STR(x) case x: return#x; 240 switch (folder) 241 { 242 CSIDL_TO_STR(CSIDL_DESKTOP); 243 CSIDL_TO_STR(CSIDL_INTERNET); 244 CSIDL_TO_STR(CSIDL_PROGRAMS); 245 CSIDL_TO_STR(CSIDL_CONTROLS); 246 CSIDL_TO_STR(CSIDL_PRINTERS); 247 CSIDL_TO_STR(CSIDL_PERSONAL); 248 CSIDL_TO_STR(CSIDL_FAVORITES); 249 CSIDL_TO_STR(CSIDL_STARTUP); 250 CSIDL_TO_STR(CSIDL_RECENT); 251 CSIDL_TO_STR(CSIDL_SENDTO); 252 CSIDL_TO_STR(CSIDL_BITBUCKET); 253 CSIDL_TO_STR(CSIDL_STARTMENU); 254 CSIDL_TO_STR(OLD_CSIDL_MYDOCUMENTS); 255 CSIDL_TO_STR(CSIDL_MYMUSIC); 256 CSIDL_TO_STR(CSIDL_MYVIDEO); 257 CSIDL_TO_STR(CSIDL_DESKTOPDIRECTORY); 258 CSIDL_TO_STR(CSIDL_DRIVES); 259 CSIDL_TO_STR(CSIDL_NETWORK); 260 CSIDL_TO_STR(CSIDL_NETHOOD); 261 CSIDL_TO_STR(CSIDL_FONTS); 262 CSIDL_TO_STR(CSIDL_TEMPLATES); 263 CSIDL_TO_STR(CSIDL_COMMON_STARTMENU); 264 CSIDL_TO_STR(CSIDL_COMMON_PROGRAMS); 265 CSIDL_TO_STR(CSIDL_COMMON_STARTUP); 266 CSIDL_TO_STR(CSIDL_COMMON_DESKTOPDIRECTORY); 267 CSIDL_TO_STR(CSIDL_APPDATA); 268 CSIDL_TO_STR(CSIDL_PRINTHOOD); 269 CSIDL_TO_STR(CSIDL_LOCAL_APPDATA); 270 CSIDL_TO_STR(CSIDL_ALTSTARTUP); 271 CSIDL_TO_STR(CSIDL_COMMON_ALTSTARTUP); 272 CSIDL_TO_STR(CSIDL_COMMON_FAVORITES); 273 CSIDL_TO_STR(CSIDL_INTERNET_CACHE); 274 CSIDL_TO_STR(CSIDL_COOKIES); 275 CSIDL_TO_STR(CSIDL_HISTORY); 276 CSIDL_TO_STR(CSIDL_COMMON_APPDATA); 277 CSIDL_TO_STR(CSIDL_WINDOWS); 278 CSIDL_TO_STR(CSIDL_SYSTEM); 279 CSIDL_TO_STR(CSIDL_PROGRAM_FILES); 280 CSIDL_TO_STR(CSIDL_MYPICTURES); 281 CSIDL_TO_STR(CSIDL_PROFILE); 282 CSIDL_TO_STR(CSIDL_SYSTEMX86); 283 CSIDL_TO_STR(CSIDL_PROGRAM_FILESX86); 284 CSIDL_TO_STR(CSIDL_PROGRAM_FILES_COMMON); 285 CSIDL_TO_STR(CSIDL_PROGRAM_FILES_COMMONX86); 286 CSIDL_TO_STR(CSIDL_COMMON_TEMPLATES); 287 CSIDL_TO_STR(CSIDL_COMMON_DOCUMENTS); 288 CSIDL_TO_STR(CSIDL_COMMON_ADMINTOOLS); 289 CSIDL_TO_STR(CSIDL_ADMINTOOLS); 290 CSIDL_TO_STR(CSIDL_CONNECTIONS); 291 CSIDL_TO_STR(CSIDL_PROFILES); 292 CSIDL_TO_STR(CSIDL_COMMON_MUSIC); 293 CSIDL_TO_STR(CSIDL_COMMON_PICTURES); 294 CSIDL_TO_STR(CSIDL_COMMON_VIDEO); 295 CSIDL_TO_STR(CSIDL_RESOURCES); 296 CSIDL_TO_STR(CSIDL_RESOURCES_LOCALIZED); 297 CSIDL_TO_STR(CSIDL_COMMON_OEM_LINKS); 298 CSIDL_TO_STR(CSIDL_CDBURN_AREA); 299 CSIDL_TO_STR(CSIDL_COMPUTERSNEARME); 300 #undef CSIDL_TO_STR 301 default: 302 sprintf(unknown, "unknown (0x%04x)", folder); 303 return unknown; 304 } 305 } 306 307 /* Standard CSIDL values (and their flags) uses only two less-significant bytes */ 308 #define NO_CSIDL 0x10000 309 #define WINE_ATTRIBUTES_OPTIONAL 0x20000 310 #define KNOWN_FOLDER(id, csidl, name, category, parent1, parent2, relative_path, parsing_name, attributes, definitionFlags) \ 311 { &id, # id, csidl, # csidl, name, category, {&parent1, &parent2}, relative_path, parsing_name, attributes, definitionFlags, __LINE__ } 312 313 /* non-published known folders test */ 314 static const GUID _FOLDERID_CryptoKeys = {0xB88F4DAA, 0xE7BD, 0x49A9, {0xB7, 0x4D, 0x02, 0x88, 0x5A, 0x5D, 0xC7, 0x65} }; 315 static const GUID _FOLDERID_DpapiKeys = {0x10C07CD0, 0xEF91, 0x4567, {0xB8, 0x50, 0x44, 0x8B, 0x77, 0xCB, 0x37, 0xF9} }; 316 static const GUID _FOLDERID_SystemCertificates = {0x54EED2E0, 0xE7CA, 0x4FDB, {0x91, 0x48, 0x0F, 0x42, 0x47, 0x29, 0x1C, 0xFA} }; 317 static const GUID _FOLDERID_CredentialManager = {0x915221FB, 0x9EFE, 0x4BDA, {0x8F, 0xD7, 0xF7, 0x8D, 0xCA, 0x77, 0x4F, 0x87} }; 318 319 struct knownFolderDef { 320 const KNOWNFOLDERID *folderId; 321 const char *sFolderId; 322 const int csidl; 323 const char *sCsidl; 324 const char *sName; 325 const KF_CATEGORY category; 326 const KNOWNFOLDERID *fidParents[2]; 327 const char *sRelativePath; 328 const char *sParsingName; 329 const DWORD attributes; 330 const KF_DEFINITION_FLAGS definitionFlags; 331 const int line; 332 }; 333 334 /* Note: content of parsing name may vary between Windows versions. 335 * As a base, values from 6.0 (Vista) were used. Some entries may contain 336 * alternative values. In that case, Windows version where the value was 337 * found is noted. 338 * 339 * The list of values for parsing name was encoded as a number of null- 340 * terminated strings placed one by one (separated by null byte only). 341 * End of list is marked by two consecutive null bytes. 342 */ 343 static const struct knownFolderDef known_folders[] = { 344 KNOWN_FOLDER(FOLDERID_AddNewPrograms, 345 NO_CSIDL, 346 "AddNewProgramsFolder", 347 KF_CATEGORY_VIRTUAL, 348 GUID_NULL, GUID_NULL, 349 NULL, 350 "::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{15eae92e-f17a-4431-9f28-805e482dafd4}\0" 351 "shell:::{26EE0668-A00A-44D7-9371-BEB064C98683}\\0\\::{15eae92e-f17a-4431-9f28-805e482dafd4}\0\0" /* 6.1 */, 352 0, 353 0), 354 KNOWN_FOLDER(FOLDERID_AdminTools, 355 CSIDL_ADMINTOOLS, 356 "Administrative Tools", 357 KF_CATEGORY_PERUSER, 358 FOLDERID_Programs, GUID_NULL, 359 "Administrative Tools", 360 NULL, 361 FILE_ATTRIBUTE_READONLY, 362 KFDF_PRECREATE), 363 KNOWN_FOLDER(FOLDERID_AppUpdates, 364 NO_CSIDL, 365 "AppUpdatesFolder", 366 KF_CATEGORY_VIRTUAL, 367 GUID_NULL, GUID_NULL, 368 NULL, 369 "::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{7b81be6a-ce2b-4676-a29e-eb907a5126c5}\\::{d450a8a1-9568-45c7-9c0e-b4f9fb4537bd}\0" 370 "::{26EE0668-A00A-44D7-9371-BEB064C98683}\\0\\::{7b81be6a-ce2b-4676-a29e-eb907a5126c5}\\::{d450a8a1-9568-45c7-9c0e-b4f9fb4537bd}\0\0" /* 6.1 */, 371 0, 372 0), 373 KNOWN_FOLDER(FOLDERID_CDBurning, 374 CSIDL_CDBURN_AREA, 375 "CD Burning", 376 KF_CATEGORY_PERUSER, 377 FOLDERID_LocalAppData, GUID_NULL, 378 "Microsoft\\Windows\\Burn\\Burn", 379 NULL, 380 FILE_ATTRIBUTE_READONLY, 381 KFDF_LOCAL_REDIRECT_ONLY), 382 KNOWN_FOLDER(FOLDERID_ChangeRemovePrograms, 383 NO_CSIDL, 384 "ChangeRemoveProgramsFolder", 385 KF_CATEGORY_VIRTUAL, 386 GUID_NULL, GUID_NULL, 387 NULL, 388 "::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{7b81be6a-ce2b-4676-a29e-eb907a5126c5}\0" 389 "::{26EE0668-A00A-44D7-9371-BEB064C98683}\\0\\::{7b81be6a-ce2b-4676-a29e-eb907a5126c5}\0\0" /* 6.1 */, 390 0, 391 0), 392 KNOWN_FOLDER(FOLDERID_CommonAdminTools, 393 CSIDL_COMMON_ADMINTOOLS, 394 "Common Administrative Tools", 395 KF_CATEGORY_COMMON, 396 FOLDERID_CommonPrograms, GUID_NULL, 397 "Administrative Tools", 398 NULL, 399 FILE_ATTRIBUTE_READONLY, 400 KFDF_PRECREATE), 401 KNOWN_FOLDER(FOLDERID_CommonOEMLinks, 402 CSIDL_COMMON_OEM_LINKS, 403 "OEM Links", 404 KF_CATEGORY_COMMON, 405 FOLDERID_ProgramData, GUID_NULL, 406 "OEM Links", 407 NULL, 408 0, 409 0), 410 KNOWN_FOLDER(FOLDERID_CommonPrograms, 411 CSIDL_COMMON_PROGRAMS, 412 "Common Programs", 413 KF_CATEGORY_COMMON, 414 FOLDERID_CommonStartMenu, GUID_NULL, 415 "Programs", 416 NULL, 417 FILE_ATTRIBUTE_READONLY, 418 KFDF_PRECREATE), 419 KNOWN_FOLDER(FOLDERID_CommonStartMenu, 420 CSIDL_COMMON_STARTMENU, 421 "Common Start Menu", 422 KF_CATEGORY_COMMON, 423 FOLDERID_ProgramData, GUID_NULL, 424 "Microsoft\\Windows\\Start Menu\0", 425 NULL, 426 FILE_ATTRIBUTE_READONLY, 427 KFDF_PRECREATE), 428 KNOWN_FOLDER(FOLDERID_CommonStartup, 429 CSIDL_COMMON_STARTUP, 430 "Common Startup", 431 KF_CATEGORY_COMMON, 432 FOLDERID_CommonPrograms, GUID_NULL, 433 "StartUp", 434 NULL, 435 FILE_ATTRIBUTE_READONLY, 436 KFDF_PRECREATE), 437 KNOWN_FOLDER(FOLDERID_CommonTemplates, 438 CSIDL_COMMON_TEMPLATES, 439 "Common Templates", 440 KF_CATEGORY_COMMON, 441 FOLDERID_ProgramData, GUID_NULL, 442 "Microsoft\\Windows\\Templates\0", 443 NULL, 444 0, 445 0), 446 KNOWN_FOLDER(FOLDERID_ComputerFolder, 447 CSIDL_DRIVES, 448 "MyComputerFolder", 449 KF_CATEGORY_VIRTUAL, 450 GUID_NULL, GUID_NULL, 451 NULL, 452 "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\0\0", 453 0, 454 0), 455 KNOWN_FOLDER(FOLDERID_ConflictFolder, 456 NO_CSIDL, 457 "ConflictFolder", 458 KF_CATEGORY_VIRTUAL, 459 GUID_NULL, GUID_NULL, 460 NULL, 461 "::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{9C73F5E5-7AE7-4E32-A8E8-8D23B85255BF}\\::{E413D040-6788-4C22-957E-175D1C513A34},\0" 462 "::{26EE0668-A00A-44D7-9371-BEB064C98683}\\0\\::{9C73F5E5-7AE7-4E32-A8E8-8D23B85255BF}\\::{E413D040-6788-4C22-957E-175D1C513A34},\0\0" /* 6.1 */, 463 0, 464 0), 465 KNOWN_FOLDER(FOLDERID_ConnectionsFolder, 466 CSIDL_CONNECTIONS, 467 "ConnectionsFolder", 468 KF_CATEGORY_VIRTUAL, 469 GUID_NULL, GUID_NULL, 470 NULL, 471 "::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{7007ACC7-3202-11D1-AAD2-00805FC1270E}\0" 472 "::{26EE0668-A00A-44D7-9371-BEB064C98683}\\0\\::{7007ACC7-3202-11D1-AAD2-00805FC1270E}\0\0" /* 6.1 */, 473 0, 474 0), 475 KNOWN_FOLDER(FOLDERID_Contacts, 476 NO_CSIDL, 477 "Contacts", 478 KF_CATEGORY_PERUSER, 479 FOLDERID_Profile, GUID_NULL, 480 "Contacts", 481 "::{59031a47-3f72-44a7-89c5-5595fe6b30ee}\\{56784854-C6CB-462B-8169-88E350ACB882}\0\0", 482 FILE_ATTRIBUTE_READONLY, 483 KFDF_ROAMABLE | KFDF_PRECREATE | KFDF_PUBLISHEXPANDEDPATH), 484 KNOWN_FOLDER(FOLDERID_ControlPanelFolder, 485 CSIDL_CONTROLS, 486 "ControlPanelFolder", 487 KF_CATEGORY_VIRTUAL, 488 GUID_NULL, GUID_NULL, 489 NULL, 490 "::{21EC2020-3AEA-1069-A2DD-08002B30309D}\0" 491 "::{26EE0668-A00A-44D7-9371-BEB064C98683}\\0\0\0" /* 6.1 */, 492 0, 493 0), 494 KNOWN_FOLDER(FOLDERID_Cookies, 495 CSIDL_COOKIES, 496 "Cookies", 497 KF_CATEGORY_PERUSER, 498 FOLDERID_RoamingAppData, FOLDERID_LocalAppData, 499 "Microsoft\\Windows\\Cookies\0Microsoft\\Windows\\INetCookies\0" /* win8 */, 500 NULL, 501 0, 502 0), 503 KNOWN_FOLDER(FOLDERID_Desktop, 504 CSIDL_DESKTOP, 505 "Desktop", 506 KF_CATEGORY_PERUSER, 507 FOLDERID_Profile, GUID_NULL, 508 "Desktop", 509 NULL, 510 FILE_ATTRIBUTE_READONLY, 511 KFDF_ROAMABLE | KFDF_PRECREATE | KFDF_PUBLISHEXPANDEDPATH), 512 KNOWN_FOLDER(FOLDERID_DeviceMetadataStore, 513 NO_CSIDL, 514 "Device Metadata Store", 515 KF_CATEGORY_COMMON, 516 FOLDERID_ProgramData, GUID_NULL, 517 "Microsoft\\Windows\\DeviceMetadataStore\0", 518 NULL, 519 0, 520 0), 521 KNOWN_FOLDER(FOLDERID_Documents, 522 CSIDL_MYDOCUMENTS, 523 "Personal", 524 KF_CATEGORY_PERUSER, 525 FOLDERID_Profile, GUID_NULL, 526 "Documents\0", 527 "::{59031a47-3f72-44a7-89c5-5595fe6b30ee}\\{FDD39AD0-238F-46AF-ADB4-6C85480369C7}\0shell:::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{A8CDFF1C-4878-43be-B5FD-F8091C1C60D0}\0\0", /* win8 */ 528 FILE_ATTRIBUTE_READONLY, 529 KFDF_ROAMABLE | KFDF_PRECREATE), 530 KNOWN_FOLDER(FOLDERID_DocumentsLibrary, 531 NO_CSIDL, 532 "DocumentsLibrary", 533 KF_CATEGORY_PERUSER, 534 FOLDERID_Libraries, GUID_NULL, 535 "Documents.library-ms\0", 536 "::{031E4825-7B94-4dc3-B131-E946B44C8DD5}\\{7b0db17d-9cd2-4a93-9733-46cc89022e7c}\0\0", 537 0, 538 KFDF_PRECREATE | KFDF_STREAM), 539 KNOWN_FOLDER(FOLDERID_Downloads, 540 NO_CSIDL, 541 "Downloads", 542 KF_CATEGORY_PERUSER, 543 FOLDERID_Profile, GUID_NULL, 544 "Downloads\0", 545 "(null)\0shell:::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{374DE290-123F-4565-9164-39C4925E467B}\0\0", /* win8 */ 546 FILE_ATTRIBUTE_READONLY, 547 KFDF_ROAMABLE | KFDF_PRECREATE | KFDF_PUBLISHEXPANDEDPATH), 548 KNOWN_FOLDER(FOLDERID_Favorites, 549 CSIDL_FAVORITES, 550 "Favorites", 551 KF_CATEGORY_PERUSER, 552 FOLDERID_Profile, GUID_NULL, 553 "Favorites\0", 554 NULL, 555 FILE_ATTRIBUTE_READONLY, 556 KFDF_ROAMABLE | KFDF_PRECREATE | KFDF_PUBLISHEXPANDEDPATH), 557 KNOWN_FOLDER(FOLDERID_Fonts, 558 CSIDL_FONTS, 559 "Fonts", 560 KF_CATEGORY_FIXED, 561 FOLDERID_Windows, GUID_NULL, 562 NULL, 563 NULL, 564 0, 565 0), 566 KNOWN_FOLDER(FOLDERID_Games, 567 NO_CSIDL, 568 "Games", 569 KF_CATEGORY_VIRTUAL, 570 GUID_NULL, GUID_NULL, 571 NULL, 572 "::{ED228FDF-9EA8-4870-83b1-96b02CFE0D52}\0\0", 573 0, 574 0), 575 KNOWN_FOLDER(FOLDERID_GameTasks, 576 NO_CSIDL, 577 "GameTasks", 578 KF_CATEGORY_PERUSER, 579 FOLDERID_LocalAppData, GUID_NULL, 580 "Microsoft\\Windows\\GameExplorer\0", 581 NULL, 582 0, 583 KFDF_LOCAL_REDIRECT_ONLY), 584 KNOWN_FOLDER(FOLDERID_History, 585 CSIDL_HISTORY, 586 "History", 587 KF_CATEGORY_PERUSER, 588 FOLDERID_LocalAppData, GUID_NULL, 589 "Microsoft\\Windows\\History\0", 590 NULL, 591 0, 592 KFDF_LOCAL_REDIRECT_ONLY), 593 KNOWN_FOLDER(FOLDERID_HomeGroup, 594 NO_CSIDL, 595 "HomeGroupFolder", 596 KF_CATEGORY_VIRTUAL, 597 GUID_NULL, GUID_NULL, 598 NULL, 599 "::{B4FB3F98-C1EA-428d-A78A-D1F5659CBA93}\0\0", 600 0, 601 0), 602 KNOWN_FOLDER(FOLDERID_ImplicitAppShortcuts, 603 NO_CSIDL, 604 "ImplicitAppShortcuts", 605 KF_CATEGORY_PERUSER, 606 FOLDERID_UserPinned, GUID_NULL, 607 "ImplicitAppShortcuts\0", 608 NULL, 609 0, 610 KFDF_PRECREATE), 611 KNOWN_FOLDER(FOLDERID_InternetCache, 612 CSIDL_INTERNET_CACHE, 613 "Cache", 614 KF_CATEGORY_PERUSER, 615 FOLDERID_LocalAppData, GUID_NULL, 616 "Microsoft\\Windows\\Temporary Internet Files\0Microsoft\\Windows\\INetCache\0\0", /* win8 */ 617 NULL, 618 0, 619 KFDF_LOCAL_REDIRECT_ONLY), 620 KNOWN_FOLDER(FOLDERID_InternetFolder, 621 CSIDL_INTERNET, 622 "InternetFolder", 623 KF_CATEGORY_VIRTUAL, 624 GUID_NULL, GUID_NULL, 625 NULL, 626 "::{871C5380-42A0-1069-A2EA-08002B30309D}\0\0", 627 0, 628 0), 629 KNOWN_FOLDER(FOLDERID_Libraries, 630 NO_CSIDL, 631 "Libraries", 632 KF_CATEGORY_PERUSER, 633 FOLDERID_RoamingAppData, GUID_NULL, 634 "Microsoft\\Windows\\Libraries\0", 635 NULL, 636 0, 637 KFDF_PRECREATE | KFDF_PUBLISHEXPANDEDPATH), 638 KNOWN_FOLDER(FOLDERID_Links, 639 NO_CSIDL, 640 "Links", 641 KF_CATEGORY_PERUSER, 642 FOLDERID_Profile, GUID_NULL, 643 "Links\0", 644 "::{59031a47-3f72-44a7-89c5-5595fe6b30ee}\\{bfb9d5e0-c6a9-404c-b2b2-ae6db6af4968}\0\0", 645 FILE_ATTRIBUTE_READONLY, 646 KFDF_ROAMABLE | KFDF_PRECREATE | KFDF_PUBLISHEXPANDEDPATH), 647 KNOWN_FOLDER(FOLDERID_LocalAppData, 648 CSIDL_LOCAL_APPDATA, 649 "Local AppData", 650 KF_CATEGORY_PERUSER, 651 FOLDERID_Profile, GUID_NULL, 652 "AppData\\Local\0", 653 NULL, 654 0, 655 KFDF_LOCAL_REDIRECT_ONLY | KFDF_PUBLISHEXPANDEDPATH), 656 KNOWN_FOLDER(FOLDERID_LocalAppDataLow, 657 NO_CSIDL, 658 "LocalAppDataLow", 659 KF_CATEGORY_PERUSER, 660 FOLDERID_Profile, GUID_NULL, 661 "AppData\\LocalLow\0", 662 NULL, 663 FILE_ATTRIBUTE_NOT_CONTENT_INDEXED, 664 KFDF_LOCAL_REDIRECT_ONLY | KFDF_PRECREATE | KFDF_PUBLISHEXPANDEDPATH), 665 KNOWN_FOLDER(FOLDERID_LocalizedResourcesDir, 666 CSIDL_RESOURCES_LOCALIZED, 667 "LocalizedResourcesDir", 668 KF_CATEGORY_FIXED, 669 GUID_NULL, GUID_NULL, 670 NULL, 671 NULL, 672 0, 673 0), 674 KNOWN_FOLDER(FOLDERID_Music, 675 CSIDL_MYMUSIC, 676 "My Music", 677 KF_CATEGORY_PERUSER, 678 FOLDERID_Profile, GUID_NULL, 679 "Music\0", 680 "::{59031a47-3f72-44a7-89c5-5595fe6b30ee}\\{4BD8D571-6D19-48D3-BE97-422220080E43}\0shell:::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{1CF1260C-4DD0-4EBB-811F-33C572699FDE}\0\0", /* win8 */ 681 FILE_ATTRIBUTE_READONLY, 682 KFDF_ROAMABLE | KFDF_PRECREATE), 683 KNOWN_FOLDER(FOLDERID_MusicLibrary, 684 NO_CSIDL, 685 "MusicLibrary", 686 KF_CATEGORY_PERUSER, 687 FOLDERID_Libraries, GUID_NULL, 688 "Music.library-ms\0", 689 "::{031E4825-7B94-4dc3-B131-E946B44C8DD5}\\{2112AB0A-C86A-4ffe-A368-0DE96E47012E}\0\0", 690 0, 691 KFDF_PRECREATE | KFDF_STREAM), 692 KNOWN_FOLDER(FOLDERID_NetHood, 693 CSIDL_NETHOOD, 694 "NetHood", 695 KF_CATEGORY_PERUSER, 696 FOLDERID_RoamingAppData, GUID_NULL, 697 "Microsoft\\Windows\\Network Shortcuts\0", 698 NULL, 699 0, 700 0), 701 KNOWN_FOLDER(FOLDERID_NetworkFolder, 702 CSIDL_NETWORK, 703 "NetworkPlacesFolder", 704 KF_CATEGORY_VIRTUAL, 705 GUID_NULL, GUID_NULL, 706 NULL, 707 "::{F02C1A0D-BE21-4350-88B0-7367FC96EF3C}\0\0", 708 0, 709 0), 710 KNOWN_FOLDER(FOLDERID_OriginalImages, 711 NO_CSIDL, 712 "Original Images", 713 KF_CATEGORY_PERUSER, 714 FOLDERID_LocalAppData, GUID_NULL, 715 "Microsoft\\Windows Photo Gallery\\Original Images\0", 716 NULL, 717 0, 718 0), 719 KNOWN_FOLDER(FOLDERID_PhotoAlbums, 720 NO_CSIDL, 721 "PhotoAlbums", 722 KF_CATEGORY_PERUSER, 723 FOLDERID_Pictures, GUID_NULL, 724 "Slide Shows\0", 725 NULL, 726 FILE_ATTRIBUTE_READONLY, 727 0), 728 KNOWN_FOLDER(FOLDERID_Pictures, 729 CSIDL_MYPICTURES, 730 "My Pictures", 731 KF_CATEGORY_PERUSER, 732 FOLDERID_Profile, GUID_NULL, 733 "Pictures\0", 734 "::{59031a47-3f72-44a7-89c5-5595fe6b30ee}\\{33E28130-4E1E-4676-835A-98395C3BC3BB}\0shell:::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{3ADD1653-EB32-4CB0-BBD7-DFA0ABB5ACCA}\0\0", /* win8 */ 735 FILE_ATTRIBUTE_READONLY, 736 KFDF_ROAMABLE | KFDF_PRECREATE), 737 KNOWN_FOLDER(FOLDERID_PicturesLibrary, 738 NO_CSIDL, 739 "PicturesLibrary", 740 KF_CATEGORY_PERUSER, 741 FOLDERID_Libraries, GUID_NULL, 742 "Pictures.library-ms\0", 743 "::{031E4825-7B94-4dc3-B131-E946B44C8DD5}\\{A990AE9F-A03B-4e80-94BC-9912D7504104}\0\0", 744 0, 745 KFDF_PRECREATE | KFDF_STREAM), 746 KNOWN_FOLDER(FOLDERID_Playlists, 747 NO_CSIDL, 748 "Playlists", 749 KF_CATEGORY_PERUSER, 750 FOLDERID_Music, GUID_NULL, 751 "Playlists\0", 752 NULL, 753 FILE_ATTRIBUTE_READONLY, 754 0), 755 KNOWN_FOLDER(FOLDERID_PrintersFolder, 756 CSIDL_PRINTERS, 757 "PrintersFolder", 758 KF_CATEGORY_VIRTUAL, 759 GUID_NULL, GUID_NULL, 760 NULL, 761 "::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{2227A280-3AEA-1069-A2DE-08002B30309D}\0\0", 762 0, 763 0), 764 KNOWN_FOLDER(FOLDERID_PrintHood, 765 CSIDL_PRINTHOOD, 766 "PrintHood", 767 KF_CATEGORY_PERUSER, 768 FOLDERID_RoamingAppData, GUID_NULL, 769 "Microsoft\\Windows\\Printer Shortcuts\0", 770 NULL, 771 0, 772 0), 773 KNOWN_FOLDER(FOLDERID_Profile, 774 CSIDL_PROFILE, 775 "Profile", 776 KF_CATEGORY_FIXED, 777 GUID_NULL, GUID_NULL, 778 NULL, 779 NULL, 780 0, 781 0), 782 KNOWN_FOLDER(FOLDERID_ProgramData, 783 CSIDL_COMMON_APPDATA, 784 "Common AppData", 785 KF_CATEGORY_FIXED, 786 GUID_NULL, GUID_NULL, 787 NULL, 788 NULL, 789 0, 790 0), 791 KNOWN_FOLDER(FOLDERID_ProgramFiles, 792 CSIDL_PROGRAM_FILES, 793 "ProgramFiles", 794 KF_CATEGORY_FIXED, 795 GUID_NULL, GUID_NULL, 796 NULL, 797 NULL, 798 FILE_ATTRIBUTE_READONLY, 799 KFDF_PRECREATE 800 ), 801 KNOWN_FOLDER(FOLDERID_ProgramFilesCommon, 802 CSIDL_PROGRAM_FILES_COMMON, 803 "ProgramFilesCommon", 804 KF_CATEGORY_FIXED, 805 GUID_NULL, GUID_NULL, 806 NULL, 807 NULL, 808 0, 809 0), 810 KNOWN_FOLDER(FOLDERID_ProgramFilesCommonX64, 811 NO_CSIDL, 812 "ProgramFilesCommonX64", 813 KF_CATEGORY_FIXED, 814 GUID_NULL, GUID_NULL, 815 NULL, 816 NULL, 817 0, 818 0), 819 KNOWN_FOLDER(FOLDERID_ProgramFilesCommonX86, 820 NO_CSIDL, 821 "ProgramFilesCommonX86", 822 KF_CATEGORY_FIXED, 823 GUID_NULL, GUID_NULL, 824 NULL, 825 NULL, 826 0, 827 0), 828 KNOWN_FOLDER(FOLDERID_ProgramFilesX64, 829 NO_CSIDL, 830 "ProgramFilesX64", 831 KF_CATEGORY_FIXED, 832 GUID_NULL, GUID_NULL, 833 NULL, 834 NULL, 835 0, 836 0), 837 KNOWN_FOLDER(FOLDERID_ProgramFilesX86, 838 CSIDL_PROGRAM_FILESX86, 839 "ProgramFilesX86", 840 KF_CATEGORY_FIXED, 841 GUID_NULL, GUID_NULL, 842 NULL, 843 NULL, 844 FILE_ATTRIBUTE_READONLY, 845 KFDF_PRECREATE), 846 KNOWN_FOLDER(FOLDERID_Programs, 847 CSIDL_PROGRAMS, 848 "Programs", 849 KF_CATEGORY_PERUSER, 850 FOLDERID_StartMenu, GUID_NULL, 851 "Programs\0", 852 NULL, 853 FILE_ATTRIBUTE_READONLY, 854 KFDF_PRECREATE), 855 KNOWN_FOLDER(FOLDERID_Public, 856 NO_CSIDL, 857 "Public", 858 KF_CATEGORY_FIXED, 859 GUID_NULL, GUID_NULL, 860 NULL, 861 "::{4336a54d-038b-4685-ab02-99bb52d3fb8b}\0" 862 "(null)\0\0" /* 6.1 */, 863 FILE_ATTRIBUTE_READONLY, 864 KFDF_PRECREATE), 865 KNOWN_FOLDER(FOLDERID_PublicDesktop, 866 CSIDL_COMMON_DESKTOPDIRECTORY, 867 "Common Desktop", 868 KF_CATEGORY_COMMON, 869 FOLDERID_Public, GUID_NULL, 870 "Desktop\0", 871 NULL, 872 FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN, 873 KFDF_PRECREATE), 874 KNOWN_FOLDER(FOLDERID_PublicDocuments, 875 CSIDL_COMMON_DOCUMENTS, 876 "Common Documents", 877 KF_CATEGORY_COMMON, 878 FOLDERID_Public, GUID_NULL, 879 "Documents\0", 880 NULL, 881 FILE_ATTRIBUTE_READONLY, 882 KFDF_PRECREATE), 883 KNOWN_FOLDER(FOLDERID_PublicDownloads, 884 NO_CSIDL, 885 "CommonDownloads", 886 KF_CATEGORY_COMMON, 887 FOLDERID_Public, GUID_NULL, 888 "Downloads\0", 889 NULL, 890 FILE_ATTRIBUTE_READONLY, 891 KFDF_PRECREATE), 892 KNOWN_FOLDER(FOLDERID_PublicGameTasks, 893 NO_CSIDL, 894 "PublicGameTasks", 895 KF_CATEGORY_COMMON, 896 FOLDERID_ProgramData, GUID_NULL, 897 "Microsoft\\Windows\\GameExplorer\0", 898 NULL, 899 0, 900 KFDF_LOCAL_REDIRECT_ONLY), 901 KNOWN_FOLDER(FOLDERID_PublicLibraries, 902 NO_CSIDL, 903 "PublicLibraries", 904 KF_CATEGORY_COMMON, 905 FOLDERID_Public, GUID_NULL, 906 "Libraries\0", 907 NULL, 908 FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN, 909 KFDF_PRECREATE), 910 KNOWN_FOLDER(FOLDERID_PublicMusic, 911 CSIDL_COMMON_MUSIC, 912 "CommonMusic", 913 KF_CATEGORY_COMMON, 914 FOLDERID_Public, GUID_NULL, 915 "Music\0", 916 NULL, 917 FILE_ATTRIBUTE_READONLY, 918 KFDF_PRECREATE), 919 KNOWN_FOLDER(FOLDERID_PublicPictures, 920 CSIDL_COMMON_PICTURES, 921 "CommonPictures", 922 KF_CATEGORY_COMMON, 923 FOLDERID_Public, GUID_NULL, 924 "Pictures\0", 925 NULL, 926 FILE_ATTRIBUTE_READONLY, 927 KFDF_PRECREATE), 928 KNOWN_FOLDER(FOLDERID_PublicRingtones, 929 NO_CSIDL, 930 "CommonRingtones", 931 KF_CATEGORY_COMMON, 932 FOLDERID_ProgramData, GUID_NULL, 933 "Microsoft\\Windows\\Ringtones\0", 934 NULL, 935 0, 936 KFDF_PRECREATE), 937 KNOWN_FOLDER(FOLDERID_PublicVideos, 938 CSIDL_COMMON_VIDEO, 939 "CommonVideo", 940 KF_CATEGORY_COMMON, 941 FOLDERID_Public, GUID_NULL, 942 "Videos\0", 943 NULL, 944 FILE_ATTRIBUTE_READONLY, 945 KFDF_PRECREATE), 946 KNOWN_FOLDER(FOLDERID_QuickLaunch, 947 NO_CSIDL, 948 "Quick Launch", 949 KF_CATEGORY_PERUSER, 950 FOLDERID_RoamingAppData, GUID_NULL, 951 "Microsoft\\Internet Explorer\\Quick Launch\0", 952 NULL, 953 0, 954 0), 955 KNOWN_FOLDER(FOLDERID_Recent, 956 CSIDL_RECENT, 957 "Recent", 958 KF_CATEGORY_PERUSER, 959 FOLDERID_RoamingAppData, GUID_NULL, 960 "Microsoft\\Windows\\Recent\0", 961 NULL, 962 FILE_ATTRIBUTE_READONLY, 963 KFDF_PRECREATE), 964 KNOWN_FOLDER(FOLDERID_RecordedTVLibrary, 965 NO_CSIDL, 966 "RecordedTVLibrary", 967 KF_CATEGORY_COMMON, 968 FOLDERID_PublicLibraries, GUID_NULL, 969 "RecordedTV.library-ms\0", 970 NULL, 971 0, 972 KFDF_PRECREATE | KFDF_STREAM), 973 KNOWN_FOLDER(FOLDERID_RecycleBinFolder, 974 CSIDL_BITBUCKET, 975 "RecycleBinFolder", 976 KF_CATEGORY_VIRTUAL, 977 GUID_NULL, GUID_NULL, 978 NULL, 979 "::{645FF040-5081-101B-9F08-00AA002F954E}\0\0", 980 0, 981 0), 982 KNOWN_FOLDER(FOLDERID_ResourceDir, 983 CSIDL_RESOURCES, 984 "ResourceDir", 985 KF_CATEGORY_FIXED, 986 GUID_NULL, GUID_NULL, 987 NULL, 988 NULL, 989 0, 990 0), 991 KNOWN_FOLDER(FOLDERID_Ringtones, 992 NO_CSIDL, 993 "Ringtones", 994 KF_CATEGORY_PERUSER, 995 FOLDERID_LocalAppData, GUID_NULL, 996 "Microsoft\\Windows\\Ringtones\0", 997 NULL, 998 0, 999 KFDF_PRECREATE), 1000 KNOWN_FOLDER(FOLDERID_RoamingAppData, 1001 CSIDL_APPDATA, 1002 "AppData", 1003 KF_CATEGORY_PERUSER, 1004 FOLDERID_Profile, GUID_NULL, 1005 "AppData\\Roaming\0", 1006 NULL, 1007 0, 1008 0), 1009 KNOWN_FOLDER(FOLDERID_SampleMusic, 1010 NO_CSIDL|WINE_ATTRIBUTES_OPTIONAL /* win8 */, 1011 "SampleMusic", 1012 KF_CATEGORY_COMMON, 1013 FOLDERID_PublicMusic, GUID_NULL, 1014 "Sample Music\0", 1015 NULL, 1016 FILE_ATTRIBUTE_READONLY, 1017 KFDF_PRECREATE), 1018 KNOWN_FOLDER(FOLDERID_SamplePictures, 1019 NO_CSIDL|WINE_ATTRIBUTES_OPTIONAL /* win8 */, 1020 "SamplePictures", 1021 KF_CATEGORY_COMMON, 1022 FOLDERID_PublicPictures, GUID_NULL, 1023 "Sample Pictures\0", 1024 NULL, 1025 FILE_ATTRIBUTE_READONLY, 1026 KFDF_PRECREATE), 1027 KNOWN_FOLDER(FOLDERID_SamplePlaylists, 1028 NO_CSIDL, 1029 "SamplePlaylists", 1030 KF_CATEGORY_COMMON, 1031 FOLDERID_PublicMusic, GUID_NULL, 1032 "Sample Playlists\0", 1033 NULL, 1034 FILE_ATTRIBUTE_READONLY, 1035 0), 1036 KNOWN_FOLDER(FOLDERID_SampleVideos, 1037 NO_CSIDL|WINE_ATTRIBUTES_OPTIONAL /* win8 */, 1038 "SampleVideos", 1039 KF_CATEGORY_COMMON, 1040 FOLDERID_PublicVideos, GUID_NULL, 1041 "Sample Videos\0", 1042 NULL, 1043 FILE_ATTRIBUTE_READONLY, 1044 KFDF_PRECREATE), 1045 KNOWN_FOLDER(FOLDERID_SavedGames, 1046 NO_CSIDL, 1047 "SavedGames", 1048 KF_CATEGORY_PERUSER, 1049 FOLDERID_Profile, GUID_NULL, 1050 "Saved Games\0", 1051 "::{59031a47-3f72-44a7-89c5-5595fe6b30ee}\\{4C5C32FF-BB9D-43b0-B5B4-2D72E54EAAA4}\0\0", 1052 FILE_ATTRIBUTE_READONLY, 1053 KFDF_ROAMABLE | KFDF_PRECREATE | KFDF_PUBLISHEXPANDEDPATH), 1054 KNOWN_FOLDER(FOLDERID_SavedSearches, 1055 NO_CSIDL, 1056 "Searches", 1057 KF_CATEGORY_PERUSER, 1058 FOLDERID_Profile, GUID_NULL, 1059 "Searches\0", 1060 "::{59031a47-3f72-44a7-89c5-5595fe6b30ee}\\{7d1d3a04-debb-4115-95cf-2f29da2920da}\0\0", 1061 FILE_ATTRIBUTE_READONLY, 1062 KFDF_PRECREATE | KFDF_PUBLISHEXPANDEDPATH), 1063 KNOWN_FOLDER(FOLDERID_SEARCH_CSC, 1064 NO_CSIDL, 1065 "CSCFolder", 1066 KF_CATEGORY_VIRTUAL, 1067 GUID_NULL, GUID_NULL, 1068 NULL, 1069 "shell:::{BD7A2E7B-21CB-41b2-A086-B309680C6B7E}\\*\0\0", 1070 0, 1071 0), 1072 KNOWN_FOLDER(FOLDERID_SearchHome, 1073 NO_CSIDL, 1074 "SearchHomeFolder", 1075 KF_CATEGORY_VIRTUAL, 1076 GUID_NULL, GUID_NULL, 1077 NULL, 1078 "::{9343812e-1c37-4a49-a12e-4b2d810d956b}\0\0", 1079 0, 1080 0), 1081 KNOWN_FOLDER(FOLDERID_SEARCH_MAPI, 1082 NO_CSIDL, 1083 "MAPIFolder", 1084 KF_CATEGORY_VIRTUAL, 1085 GUID_NULL, GUID_NULL, 1086 NULL, 1087 "shell:::{89D83576-6BD1-4C86-9454-BEB04E94C819}\\*\0\0", 1088 0, 1089 0), 1090 KNOWN_FOLDER(FOLDERID_SendTo, 1091 CSIDL_SENDTO, 1092 "SendTo", 1093 KF_CATEGORY_PERUSER, 1094 FOLDERID_RoamingAppData, GUID_NULL, 1095 "Microsoft\\Windows\\SendTo\0", 1096 NULL, 1097 0, 1098 0), 1099 KNOWN_FOLDER(FOLDERID_SidebarDefaultParts, 1100 NO_CSIDL, 1101 "Default Gadgets", 1102 KF_CATEGORY_COMMON, 1103 FOLDERID_ProgramFiles, GUID_NULL, 1104 "Windows Sidebar\\Gadgets\0", 1105 NULL, 1106 0, 1107 0), 1108 KNOWN_FOLDER(FOLDERID_SidebarParts, 1109 NO_CSIDL, 1110 "Gadgets", 1111 KF_CATEGORY_PERUSER, 1112 FOLDERID_LocalAppData, GUID_NULL, 1113 "Microsoft\\Windows Sidebar\\Gadgets\0", 1114 NULL, 1115 0, 1116 0), 1117 KNOWN_FOLDER(FOLDERID_StartMenu, 1118 CSIDL_STARTMENU, 1119 "Start Menu", 1120 KF_CATEGORY_PERUSER, 1121 FOLDERID_RoamingAppData, GUID_NULL, 1122 "Microsoft\\Windows\\Start Menu\0", 1123 NULL, 1124 FILE_ATTRIBUTE_READONLY, 1125 KFDF_PRECREATE), 1126 KNOWN_FOLDER(FOLDERID_Startup, 1127 CSIDL_STARTUP, 1128 "Startup", 1129 KF_CATEGORY_PERUSER, 1130 FOLDERID_Programs, GUID_NULL, 1131 "StartUp\0", 1132 NULL, 1133 FILE_ATTRIBUTE_READONLY, 1134 KFDF_PRECREATE), 1135 KNOWN_FOLDER(FOLDERID_SyncManagerFolder, 1136 NO_CSIDL, 1137 "SyncCenterFolder", 1138 KF_CATEGORY_VIRTUAL, 1139 GUID_NULL, GUID_NULL, 1140 NULL, 1141 "::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{9C73F5E5-7AE7-4E32-A8E8-8D23B85255BF}\0" 1142 "::{26EE0668-A00A-44D7-9371-BEB064C98683}\\0\\::{9C73F5E5-7AE7-4E32-A8E8-8D23B85255BF}\0\0" /* 6.1 */, 1143 0, 1144 0), 1145 KNOWN_FOLDER(FOLDERID_SyncResultsFolder, 1146 NO_CSIDL, 1147 "SyncResultsFolder", 1148 KF_CATEGORY_VIRTUAL, 1149 GUID_NULL, GUID_NULL, 1150 NULL, 1151 "::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{9C73F5E5-7AE7-4E32-A8E8-8D23B85255BF}\\::{BC48B32F-5910-47F5-8570-5074A8A5636A},\0" 1152 "::{26EE0668-A00A-44D7-9371-BEB064C98683}\\0\\::{9C73F5E5-7AE7-4E32-A8E8-8D23B85255BF}\\::{BC48B32F-5910-47F5-8570-5074A8A5636A},\0\0", 1153 0, 1154 0), 1155 KNOWN_FOLDER(FOLDERID_SyncSetupFolder, 1156 NO_CSIDL, 1157 "SyncSetupFolder", 1158 KF_CATEGORY_VIRTUAL, 1159 GUID_NULL, GUID_NULL, 1160 NULL, 1161 "::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{9C73F5E5-7AE7-4E32-A8E8-8D23B85255BF}\\::{F1390A9A-A3F4-4E5D-9C5F-98F3BD8D935C},\0" 1162 "::{26EE0668-A00A-44D7-9371-BEB064C98683}\\0\\::{9C73F5E5-7AE7-4E32-A8E8-8D23B85255BF}\\::{F1390A9A-A3F4-4E5D-9C5F-98F3BD8D935C},\0\0" /* 6.1 */, 1163 0, 1164 0), 1165 KNOWN_FOLDER(FOLDERID_System, 1166 CSIDL_SYSTEM, 1167 "System", 1168 KF_CATEGORY_FIXED, 1169 GUID_NULL, GUID_NULL, 1170 NULL, 1171 NULL, 1172 0, 1173 0), 1174 KNOWN_FOLDER(FOLDERID_SystemX86, 1175 CSIDL_SYSTEMX86, 1176 "SystemX86", 1177 KF_CATEGORY_FIXED, 1178 GUID_NULL, GUID_NULL, 1179 NULL, 1180 NULL, 1181 0, 1182 0), 1183 KNOWN_FOLDER(FOLDERID_Templates, 1184 CSIDL_TEMPLATES, 1185 "Templates", 1186 KF_CATEGORY_PERUSER, 1187 FOLDERID_RoamingAppData, GUID_NULL, 1188 "Microsoft\\Windows\\Templates\0", 1189 NULL, 1190 0, 1191 0), 1192 KNOWN_FOLDER(FOLDERID_UserPinned, 1193 NO_CSIDL, 1194 "User Pinned", 1195 KF_CATEGORY_PERUSER, 1196 FOLDERID_QuickLaunch, GUID_NULL, 1197 "User Pinned\0", 1198 NULL, 1199 FILE_ATTRIBUTE_HIDDEN, 1200 KFDF_PRECREATE), 1201 KNOWN_FOLDER(FOLDERID_UserProfiles, 1202 NO_CSIDL, 1203 "UserProfiles", 1204 KF_CATEGORY_FIXED, 1205 GUID_NULL, GUID_NULL, 1206 NULL, 1207 NULL, 1208 FILE_ATTRIBUTE_READONLY, 1209 KFDF_PRECREATE), 1210 KNOWN_FOLDER(FOLDERID_UserProgramFiles, 1211 NO_CSIDL, 1212 "UserProgramFiles", 1213 KF_CATEGORY_PERUSER, 1214 FOLDERID_LocalAppData, GUID_NULL, 1215 "Programs\0", 1216 NULL, 1217 0, 1218 0), 1219 KNOWN_FOLDER(FOLDERID_UserProgramFilesCommon, 1220 NO_CSIDL, 1221 "UserProgramFilesCommon", 1222 KF_CATEGORY_PERUSER, 1223 FOLDERID_UserProgramFiles, GUID_NULL, 1224 "Common\0", 1225 NULL, 1226 0, 1227 0), 1228 KNOWN_FOLDER(FOLDERID_UsersFiles, 1229 NO_CSIDL, 1230 "UsersFilesFolder", 1231 KF_CATEGORY_VIRTUAL, 1232 GUID_NULL, GUID_NULL, 1233 NULL, 1234 "::{59031a47-3f72-44a7-89c5-5595fe6b30ee}\0\0", 1235 0, 1236 0), 1237 KNOWN_FOLDER(FOLDERID_UsersLibraries, 1238 NO_CSIDL, 1239 "UsersLibrariesFolder", 1240 KF_CATEGORY_VIRTUAL, 1241 GUID_NULL, GUID_NULL, 1242 NULL, 1243 "::{031E4825-7B94-4dc3-B131-E946B44C8DD5}\0\0", 1244 0, 1245 0), 1246 KNOWN_FOLDER(FOLDERID_Videos, 1247 CSIDL_MYVIDEO, 1248 "My Video", 1249 KF_CATEGORY_PERUSER, 1250 FOLDERID_Profile, GUID_NULL, 1251 "Videos\0", 1252 "::{59031a47-3f72-44a7-89c5-5595fe6b30ee}\\{18989B1D-99B5-455B-841C-AB7C74E4DDFC}\0shell:::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{A0953C92-50DC-43BF-BE83-3742FED03C9C}\0\0", /* win8 */ 1253 FILE_ATTRIBUTE_READONLY, 1254 KFDF_ROAMABLE | KFDF_PRECREATE), 1255 KNOWN_FOLDER(FOLDERID_VideosLibrary, 1256 NO_CSIDL, 1257 "VideosLibrary", 1258 KF_CATEGORY_PERUSER, 1259 FOLDERID_Libraries, GUID_NULL, 1260 "Videos.library-ms\0", 1261 "::{031E4825-7B94-4dc3-B131-E946B44C8DD5}\\{491E922F-5643-4af4-A7EB-4E7A138D8174}\0\0", 1262 0, 1263 KFDF_PRECREATE | KFDF_STREAM), 1264 KNOWN_FOLDER(FOLDERID_Windows, 1265 CSIDL_WINDOWS, 1266 "Windows", 1267 KF_CATEGORY_FIXED, 1268 GUID_NULL, GUID_NULL, 1269 NULL, 1270 NULL, 1271 0, 1272 0), 1273 KNOWN_FOLDER(_FOLDERID_CredentialManager, 1274 NO_CSIDL, 1275 "CredentialManager", 1276 KF_CATEGORY_FIXED, 1277 GUID_NULL, GUID_NULL, 1278 NULL, 1279 NULL, 1280 0, 1281 0), 1282 KNOWN_FOLDER(_FOLDERID_CryptoKeys, 1283 NO_CSIDL, 1284 "CryptoKeys", 1285 KF_CATEGORY_FIXED, 1286 GUID_NULL, GUID_NULL, 1287 NULL, 1288 NULL, 1289 0, 1290 0), 1291 KNOWN_FOLDER(_FOLDERID_DpapiKeys, 1292 NO_CSIDL, 1293 "DpapiKeys", 1294 KF_CATEGORY_FIXED, 1295 GUID_NULL, GUID_NULL, 1296 NULL, 1297 NULL, 1298 0, 1299 0), 1300 KNOWN_FOLDER(_FOLDERID_SystemCertificates, 1301 NO_CSIDL, 1302 "SystemCertificates", 1303 KF_CATEGORY_FIXED, 1304 GUID_NULL, GUID_NULL, 1305 NULL, 1306 NULL, 1307 0, 1308 0), 1309 }; 1310 #undef KNOWN_FOLDER 1311 BOOL known_folder_found[ARRAY_SIZE(known_folders)]; 1312 1313 static void test_parameters(void) 1314 { 1315 LPITEMIDLIST pidl = NULL; 1316 char path[MAX_PATH]; 1317 HRESULT hr; 1318 1319 if (pSHGetFolderLocation) 1320 { 1321 /* check a bogus CSIDL: */ 1322 pidl = NULL; 1323 hr = pSHGetFolderLocation(NULL, 0xeeee, NULL, 0, &pidl); 1324 ok(hr == E_INVALIDARG, "got 0x%08x, expected E_INVALIDARG\n", hr); 1325 if (hr == S_OK) IMalloc_Free(pMalloc, pidl); 1326 1327 /* check a bogus user token: */ 1328 pidl = NULL; 1329 hr = pSHGetFolderLocation(NULL, CSIDL_FAVORITES, (HANDLE)2, 0, &pidl); 1330 ok(hr == E_FAIL || hr == E_HANDLE, "got 0x%08x, expected E_FAIL or E_HANDLE\n", hr); 1331 if (hr == S_OK) IMalloc_Free(pMalloc, pidl); 1332 1333 /* a NULL pidl pointer crashes, so don't test it */ 1334 } 1335 1336 if (pSHGetSpecialFolderLocation) 1337 { 1338 if (0) 1339 /* crashes */ 1340 SHGetSpecialFolderLocation(NULL, 0, NULL); 1341 1342 hr = pSHGetSpecialFolderLocation(NULL, 0xeeee, &pidl); 1343 ok(hr == E_INVALIDARG, "got returned 0x%08x\n", hr); 1344 } 1345 1346 if (pSHGetFolderPathA) 1347 { 1348 /* expect 2's a bogus handle, especially since we didn't open it */ 1349 hr = pSHGetFolderPathA(NULL, CSIDL_DESKTOP, (HANDLE)2, SHGFP_TYPE_DEFAULT, path); 1350 ok(hr == E_FAIL || hr == E_HANDLE || /* Vista and 2k8 */ 1351 broken(hr == S_OK), /* W2k and Me */ "got 0x%08x, expected E_FAIL\n", hr); 1352 1353 hr = pSHGetFolderPathA(NULL, 0xeeee, NULL, SHGFP_TYPE_DEFAULT, path); 1354 ok(hr == E_INVALIDARG, "got 0x%08x, expected E_INVALIDARG\n", hr); 1355 } 1356 1357 if (pSHGetSpecialFolderPathA) 1358 { 1359 BOOL ret; 1360 1361 if (0) 1362 pSHGetSpecialFolderPathA(NULL, NULL, CSIDL_BITBUCKET, FALSE); 1363 1364 /* odd but true: calling with a NULL path still succeeds if it's a real 1365 * dir (on some windows platform). on winME it generates exception. 1366 */ 1367 ret = pSHGetSpecialFolderPathA(NULL, path, CSIDL_PROGRAMS, FALSE); 1368 ok(ret, "got %d\n", ret); 1369 1370 ret = pSHGetSpecialFolderPathA(NULL, path, 0xeeee, FALSE); 1371 ok(!ret, "got %d\n", ret); 1372 } 1373 } 1374 1375 /* Returns the folder's PIDL type, or 0xff if one can't be found. */ 1376 static BYTE testSHGetFolderLocation(int folder) 1377 { 1378 LPITEMIDLIST pidl; 1379 HRESULT hr; 1380 BYTE ret = 0xff; 1381 1382 /* treat absence of function as success */ 1383 if (!pSHGetFolderLocation) return TRUE; 1384 1385 pidl = NULL; 1386 hr = pSHGetFolderLocation(NULL, folder, NULL, 0, &pidl); 1387 if (hr == S_OK) 1388 { 1389 if (pidl) 1390 { 1391 LPITEMIDLIST pidlLast = pILFindLastID(pidl); 1392 1393 ok(pidlLast != NULL, "%s: ILFindLastID failed\n", 1394 getFolderName(folder)); 1395 if (pidlLast) 1396 ret = pidlLast->mkid.abID[0]; 1397 IMalloc_Free(pMalloc, pidl); 1398 } 1399 } 1400 return ret; 1401 } 1402 1403 /* Returns the folder's PIDL type, or 0xff if one can't be found. */ 1404 static BYTE testSHGetSpecialFolderLocation(int folder) 1405 { 1406 LPITEMIDLIST pidl; 1407 HRESULT hr; 1408 BYTE ret = 0xff; 1409 1410 /* treat absence of function as success */ 1411 if (!pSHGetSpecialFolderLocation) return TRUE; 1412 1413 pidl = NULL; 1414 hr = pSHGetSpecialFolderLocation(NULL, folder, &pidl); 1415 if (hr == S_OK) 1416 { 1417 if (pidl) 1418 { 1419 LPITEMIDLIST pidlLast = pILFindLastID(pidl); 1420 1421 ok(pidlLast != NULL, 1422 "%s: ILFindLastID failed\n", getFolderName(folder)); 1423 if (pidlLast) 1424 ret = pidlLast->mkid.abID[0]; 1425 IMalloc_Free(pMalloc, pidl); 1426 } 1427 } 1428 return ret; 1429 } 1430 1431 static void test_SHGetFolderPath(BOOL optional, int folder) 1432 { 1433 char path[MAX_PATH]; 1434 HRESULT hr; 1435 1436 if (!pSHGetFolderPathA) return; 1437 1438 hr = pSHGetFolderPathA(NULL, folder, NULL, SHGFP_TYPE_CURRENT, path); 1439 ok(hr == S_OK || optional, 1440 "SHGetFolderPathA(NULL, %s, NULL, SHGFP_TYPE_CURRENT, path) failed: 0x%08x\n", getFolderName(folder), hr); 1441 } 1442 1443 static void test_SHGetSpecialFolderPath(BOOL optional, int folder) 1444 { 1445 char path[MAX_PATH]; 1446 BOOL ret; 1447 1448 if (!pSHGetSpecialFolderPathA) return; 1449 1450 ret = pSHGetSpecialFolderPathA(NULL, path, folder, FALSE); 1451 if (ret && winetest_interactive) 1452 printf("%s: %s\n", getFolderName(folder), path); 1453 ok(ret || optional, 1454 "SHGetSpecialFolderPathA(NULL, path, %s, FALSE) failed\n", 1455 getFolderName(folder)); 1456 } 1457 1458 static void test_ShellValues(const struct shellExpectedValues testEntries[], 1459 int numEntries, BOOL optional) 1460 { 1461 int i; 1462 1463 for (i = 0; i < numEntries; i++) 1464 { 1465 BYTE type; 1466 int j; 1467 BOOL foundTypeMatch = FALSE; 1468 1469 if (pSHGetFolderLocation) 1470 { 1471 type = testSHGetFolderLocation(testEntries[i].folder); 1472 for (j = 0; !foundTypeMatch && j < testEntries[i].numTypes; j++) 1473 if (testEntries[i].types[j] == type) 1474 foundTypeMatch = TRUE; 1475 ok(foundTypeMatch || optional || broken(type == 0xff) /* Win9x */, 1476 "%s has unexpected type %d (0x%02x)\n", 1477 getFolderName(testEntries[i].folder), type, type); 1478 } 1479 type = testSHGetSpecialFolderLocation(testEntries[i].folder); 1480 for (j = 0, foundTypeMatch = FALSE; !foundTypeMatch && 1481 j < testEntries[i].numTypes; j++) 1482 if (testEntries[i].types[j] == type) 1483 foundTypeMatch = TRUE; 1484 ok(foundTypeMatch || optional || broken(type == 0xff) /* Win9x */, 1485 "%s has unexpected type %d (0x%02x)\n", 1486 getFolderName(testEntries[i].folder), type, type); 1487 switch (type) 1488 { 1489 case PT_FOLDER: 1490 case PT_DRIVE: 1491 case PT_DRIVE2: 1492 case PT_IESPECIAL2: 1493 test_SHGetFolderPath(optional, testEntries[i].folder); 1494 test_SHGetSpecialFolderPath(optional, testEntries[i].folder); 1495 break; 1496 } 1497 } 1498 } 1499 1500 /* Attempts to verify that the folder path corresponding to the folder CSIDL 1501 * value has the same value as the environment variable with name envVar. 1502 * Doesn't mind if SHGetSpecialFolderPath fails for folder or if envVar isn't 1503 * set in this environment; different OS and shell version behave differently. 1504 * However, if both are present, fails if envVar's value is not the same 1505 * (byte-for-byte) as what SHGetSpecialFolderPath returns. 1506 */ 1507 static void matchSpecialFolderPathToEnv(int folder, const char *envVar) 1508 { 1509 char path[MAX_PATH]; 1510 1511 if (!pSHGetSpecialFolderPathA) return; 1512 1513 if (pSHGetSpecialFolderPathA(NULL, path, folder, FALSE)) 1514 { 1515 char *envVal = getenv(envVar); 1516 1517 ok(!envVal || !lstrcmpiA(envVal, path), 1518 "%%%s%% does not match SHGetSpecialFolderPath:\n" 1519 "%%%s%% is %s\nSHGetSpecialFolderPath returns %s\n", 1520 envVar, envVar, envVal, path); 1521 } 1522 } 1523 1524 /* Attempts to match the GUID returned by SHGetFolderLocation for folder with 1525 * GUID. Assumes the type of the returned PIDL is in fact a GUID, but doesn't 1526 * fail if it isn't--that check should already have been done. 1527 * Fails if the returned PIDL is a GUID whose value does not match guid. 1528 */ 1529 static void matchGUID(int folder, const GUID *guid, const GUID *guid_alt) 1530 { 1531 LPITEMIDLIST pidl; 1532 HRESULT hr; 1533 1534 if (!pSHGetFolderLocation) return; 1535 if (!guid) return; 1536 1537 pidl = NULL; 1538 hr = pSHGetFolderLocation(NULL, folder, NULL, 0, &pidl); 1539 if (hr == S_OK) 1540 { 1541 LPITEMIDLIST pidlLast = pILFindLastID(pidl); 1542 1543 if (pidlLast && (pidlLast->mkid.abID[0] == PT_SHELLEXT || 1544 pidlLast->mkid.abID[0] == PT_GUID)) 1545 { 1546 GUID *shellGuid = (GUID *)(pidlLast->mkid.abID + 2); 1547 1548 if (!guid_alt) 1549 ok(IsEqualIID(shellGuid, guid), 1550 "%s: got GUID %s, expected %s\n", getFolderName(folder), 1551 wine_dbgstr_guid(shellGuid), wine_dbgstr_guid(guid)); 1552 else 1553 ok(IsEqualIID(shellGuid, guid) || 1554 IsEqualIID(shellGuid, guid_alt), 1555 "%s: got GUID %s, expected %s or %s\n", getFolderName(folder), 1556 wine_dbgstr_guid(shellGuid), wine_dbgstr_guid(guid), wine_dbgstr_guid(guid_alt)); 1557 } 1558 IMalloc_Free(pMalloc, pidl); 1559 } 1560 } 1561 1562 /* Checks the PIDL type of all the known values. */ 1563 static void test_PidlTypes(void) 1564 { 1565 /* Desktop */ 1566 test_SHGetFolderPath(FALSE, CSIDL_DESKTOP); 1567 test_SHGetSpecialFolderPath(FALSE, CSIDL_DESKTOP); 1568 1569 test_ShellValues(requiredShellValues, ARRAY_SIZE(requiredShellValues), FALSE); 1570 test_ShellValues(optionalShellValues, ARRAY_SIZE(optionalShellValues), TRUE); 1571 } 1572 1573 /* FIXME: Should be in shobjidl.idl */ 1574 DEFINE_GUID(CLSID_NetworkExplorerFolder, 0xF02C1A0D, 0xBE21, 0x4350, 0x88, 0xB0, 0x73, 0x67, 0xFC, 0x96, 0xEF, 0x3C); 1575 DEFINE_GUID(_CLSID_Documents, 0xA8CDFF1C, 0x4878, 0x43be, 0xB5, 0xFD, 0xF8, 0x09, 0x1C, 0x1C, 0x60, 0xD0); 1576 1577 /* Verifies various shell virtual folders have the correct well-known GUIDs. */ 1578 static void test_GUIDs(void) 1579 { 1580 matchGUID(CSIDL_BITBUCKET, &CLSID_RecycleBin, NULL); 1581 matchGUID(CSIDL_CONTROLS, &CLSID_ControlPanel, NULL); 1582 matchGUID(CSIDL_DRIVES, &CLSID_MyComputer, NULL); 1583 matchGUID(CSIDL_INTERNET, &CLSID_Internet, NULL); 1584 matchGUID(CSIDL_NETWORK, &CLSID_NetworkPlaces, &CLSID_NetworkExplorerFolder); /* Vista and higher */ 1585 matchGUID(CSIDL_PERSONAL, &CLSID_MyDocuments, &_CLSID_Documents /* win8 */); 1586 matchGUID(CSIDL_COMMON_DOCUMENTS, &CLSID_CommonDocuments, NULL); 1587 matchGUID(CSIDL_PRINTERS, &CLSID_Printers, NULL); 1588 } 1589 1590 /* Verifies various shell paths match the environment variables to which they 1591 * correspond. 1592 */ 1593 static void test_EnvVars(void) 1594 { 1595 matchSpecialFolderPathToEnv(CSIDL_PROGRAM_FILES, "ProgramFiles"); 1596 matchSpecialFolderPathToEnv(CSIDL_APPDATA, "APPDATA"); 1597 matchSpecialFolderPathToEnv(CSIDL_PROFILE, "USERPROFILE"); 1598 matchSpecialFolderPathToEnv(CSIDL_WINDOWS, "SystemRoot"); 1599 matchSpecialFolderPathToEnv(CSIDL_WINDOWS, "windir"); 1600 matchSpecialFolderPathToEnv(CSIDL_PROGRAM_FILES_COMMON, "CommonProgramFiles"); 1601 /* this is only set on Wine, but can't hurt to verify it: */ 1602 matchSpecialFolderPathToEnv(CSIDL_SYSTEM, "winsysdir"); 1603 } 1604 1605 /* Loosely based on PathRemoveBackslashA from dlls/shlwapi/path.c */ 1606 static BOOL myPathIsRootA(LPCSTR lpszPath) 1607 { 1608 if (lpszPath && *lpszPath && 1609 lpszPath[1] == ':' && lpszPath[2] == '\\' && lpszPath[3] == '\0') 1610 return TRUE; /* X:\ */ 1611 return FALSE; 1612 } 1613 static LPSTR myPathRemoveBackslashA( LPSTR lpszPath ) 1614 { 1615 LPSTR szTemp = NULL; 1616 1617 if(lpszPath) 1618 { 1619 szTemp = CharPrevA(lpszPath, lpszPath + strlen(lpszPath)); 1620 if (!myPathIsRootA(lpszPath) && *szTemp == '\\') 1621 *szTemp = '\0'; 1622 } 1623 return szTemp; 1624 } 1625 1626 /* Verifies the shell path for CSIDL_WINDOWS matches the return from 1627 * GetWindowsDirectory. If SHGetSpecialFolderPath fails, no harm, no foul--not 1628 * every shell32 version supports CSIDL_WINDOWS. 1629 */ 1630 static void testWinDir(void) 1631 { 1632 char windowsShellPath[MAX_PATH], windowsDir[MAX_PATH] = { 0 }; 1633 1634 if (!pSHGetSpecialFolderPathA) return; 1635 1636 if (pSHGetSpecialFolderPathA(NULL, windowsShellPath, CSIDL_WINDOWS, FALSE)) 1637 { 1638 myPathRemoveBackslashA(windowsShellPath); 1639 GetWindowsDirectoryA(windowsDir, sizeof(windowsDir)); 1640 myPathRemoveBackslashA(windowsDir); 1641 ok(!lstrcmpiA(windowsDir, windowsShellPath), 1642 "GetWindowsDirectory returns %s SHGetSpecialFolderPath returns %s\n", 1643 windowsDir, windowsShellPath); 1644 } 1645 } 1646 1647 /* Verifies the shell path for CSIDL_SYSTEM matches the return from 1648 * GetSystemDirectory. If SHGetSpecialFolderPath fails, no harm, 1649 * no foul--not every shell32 version supports CSIDL_SYSTEM. 1650 */ 1651 static void testSystemDir(void) 1652 { 1653 char systemShellPath[MAX_PATH], systemDir[MAX_PATH], systemDirx86[MAX_PATH]; 1654 1655 if (!pSHGetSpecialFolderPathA) return; 1656 1657 GetSystemDirectoryA(systemDir, sizeof(systemDir)); 1658 myPathRemoveBackslashA(systemDir); 1659 if (pSHGetSpecialFolderPathA(NULL, systemShellPath, CSIDL_SYSTEM, FALSE)) 1660 { 1661 myPathRemoveBackslashA(systemShellPath); 1662 ok(!lstrcmpiA(systemDir, systemShellPath), 1663 "GetSystemDirectory returns %s SHGetSpecialFolderPath returns %s\n", 1664 systemDir, systemShellPath); 1665 } 1666 1667 if (!pGetSystemWow64DirectoryA || !pGetSystemWow64DirectoryA(systemDirx86, sizeof(systemDirx86))) 1668 GetSystemDirectoryA(systemDirx86, sizeof(systemDirx86)); 1669 myPathRemoveBackslashA(systemDirx86); 1670 if (pSHGetSpecialFolderPathA(NULL, systemShellPath, CSIDL_SYSTEMX86, FALSE)) 1671 { 1672 myPathRemoveBackslashA(systemShellPath); 1673 ok(!lstrcmpiA(systemDirx86, systemShellPath) || broken(!lstrcmpiA(systemDir, systemShellPath)), 1674 "GetSystemDirectory returns %s SHGetSpecialFolderPath returns %s\n", 1675 systemDir, systemShellPath); 1676 } 1677 } 1678 1679 /* Globals used by subprocesses */ 1680 static int myARGC; 1681 static char **myARGV; 1682 static char base[MAX_PATH]; 1683 static char selfname[MAX_PATH]; 1684 1685 static BOOL init(void) 1686 { 1687 myARGC = winetest_get_mainargs(&myARGV); 1688 if (!GetCurrentDirectoryA(sizeof(base), base)) return FALSE; 1689 strcpy(selfname, myARGV[0]); 1690 return TRUE; 1691 } 1692 1693 static void doChild(const char *arg) 1694 { 1695 char path[MAX_PATH]; 1696 HRESULT hr; 1697 1698 if (arg[0] == '1') 1699 { 1700 LPITEMIDLIST pidl; 1701 char *p; 1702 1703 /* test what happens when CSIDL_FAVORITES is set to a nonexistent directory */ 1704 1705 /* test some failure cases first: */ 1706 hr = pSHGetFolderPathA(NULL, CSIDL_FAVORITES, NULL, SHGFP_TYPE_CURRENT, path); 1707 ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), 1708 "SHGetFolderPath returned 0x%08x, expected 0x80070002\n", hr); 1709 1710 pidl = NULL; 1711 hr = pSHGetFolderLocation(NULL, CSIDL_FAVORITES, NULL, 0, &pidl); 1712 ok(hr == E_FAIL || hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), 1713 "SHGetFolderLocation returned 0x%08x\n", hr); 1714 if (hr == S_OK && pidl) IMalloc_Free(pMalloc, pidl); 1715 1716 ok(!pSHGetSpecialFolderPathA(NULL, path, CSIDL_FAVORITES, FALSE), 1717 "SHGetSpecialFolderPath succeeded, expected failure\n"); 1718 1719 pidl = NULL; 1720 hr = pSHGetSpecialFolderLocation(NULL, CSIDL_FAVORITES, &pidl); 1721 ok(hr == E_FAIL || hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), 1722 "SHGetFolderLocation returned 0x%08x\n", hr); 1723 1724 if (hr == S_OK && pidl) IMalloc_Free(pMalloc, pidl); 1725 1726 /* now test success: */ 1727 hr = pSHGetFolderPathA(NULL, CSIDL_FAVORITES | CSIDL_FLAG_CREATE, NULL, 1728 SHGFP_TYPE_CURRENT, path); 1729 ok (hr == S_OK, "got 0x%08x\n", hr); 1730 if (hr == S_OK) 1731 { 1732 BOOL ret; 1733 1734 trace("CSIDL_FAVORITES was changed to %s\n", path); 1735 ret = CreateDirectoryA(path, NULL); 1736 ok(!ret, "expected failure with ERROR_ALREADY_EXISTS\n"); 1737 if (!ret) 1738 ok(GetLastError() == ERROR_ALREADY_EXISTS, 1739 "got %d, expected ERROR_ALREADY_EXISTS\n", GetLastError()); 1740 1741 p = path + strlen(path); 1742 strcpy(p, "\\desktop.ini"); 1743 DeleteFileA(path); 1744 *p = 0; 1745 SetFileAttributesA( path, FILE_ATTRIBUTE_NORMAL ); 1746 ret = RemoveDirectoryA(path); 1747 ok( ret, "failed to remove %s error %u\n", path, GetLastError() ); 1748 } 1749 } 1750 else if (arg[0] == '2') 1751 { 1752 /* make sure SHGetFolderPath still succeeds when the 1753 original value of CSIDL_FAVORITES is restored. */ 1754 hr = pSHGetFolderPathA(NULL, CSIDL_FAVORITES | CSIDL_FLAG_CREATE, NULL, 1755 SHGFP_TYPE_CURRENT, path); 1756 ok(hr == S_OK, "SHGetFolderPath failed: 0x%08x\n", hr); 1757 } 1758 } 1759 1760 /* Tests the return values from the various shell functions both with and 1761 * without the use of the CSIDL_FLAG_CREATE flag. This flag only appeared in 1762 * version 5 of the shell, so don't test unless it's at least version 5. 1763 * The test reads a value from the registry, modifies it, calls 1764 * SHGetFolderPath once with the CSIDL_FLAG_CREATE flag, and immediately 1765 * afterward without it. Then it restores the registry and deletes the folder 1766 * that was created. 1767 * One oddity with respect to restoration: shell32 caches somehow, so it needs 1768 * to be reloaded in order to see the correct (restored) value. 1769 * Some APIs unrelated to the ones under test may fail, but I expect they're 1770 * covered by other unit tests; I just print out something about failure to 1771 * help trace what's going on. 1772 */ 1773 static void test_NonExistentPath(void) 1774 { 1775 static const char userShellFolders[] = 1776 "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders"; 1777 char originalPath[MAX_PATH], modifiedPath[MAX_PATH]; 1778 HKEY key; 1779 1780 if (!pSHGetFolderPathA) return; 1781 if (!pSHGetFolderLocation) return; 1782 if (!pSHGetSpecialFolderPathA) return; 1783 if (!pSHGetSpecialFolderLocation) return; 1784 if (!pSHFileOperationA) return; 1785 if (shellVersion.dwMajorVersion < 5) return; 1786 1787 if (!RegOpenKeyExA(HKEY_CURRENT_USER, userShellFolders, 0, KEY_ALL_ACCESS, 1788 &key)) 1789 { 1790 DWORD len, type; 1791 1792 len = sizeof(originalPath); 1793 if (!RegQueryValueExA(key, "Favorites", NULL, &type, 1794 (LPBYTE)&originalPath, &len)) 1795 { 1796 size_t len = strlen(originalPath); 1797 1798 memcpy(modifiedPath, originalPath, len); 1799 modifiedPath[len++] = '2'; 1800 modifiedPath[len++] = '\0'; 1801 trace("Changing CSIDL_FAVORITES to %s\n", modifiedPath); 1802 if (!RegSetValueExA(key, "Favorites", 0, type, 1803 (LPBYTE)modifiedPath, len)) 1804 { 1805 char buffer[MAX_PATH+20]; 1806 STARTUPINFOA startup; 1807 PROCESS_INFORMATION info; 1808 1809 sprintf(buffer, "%s tests/shellpath.c 1", selfname); 1810 memset(&startup, 0, sizeof(startup)); 1811 startup.cb = sizeof(startup); 1812 startup.dwFlags = STARTF_USESHOWWINDOW; 1813 startup.wShowWindow = SW_SHOWNORMAL; 1814 CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, 1815 &startup, &info); 1816 winetest_wait_child_process( info.hProcess ); 1817 1818 /* restore original values: */ 1819 trace("Restoring CSIDL_FAVORITES to %s\n", originalPath); 1820 RegSetValueExA(key, "Favorites", 0, type, (LPBYTE) originalPath, 1821 strlen(originalPath) + 1); 1822 RegFlushKey(key); 1823 1824 sprintf(buffer, "%s tests/shellpath.c 2", selfname); 1825 memset(&startup, 0, sizeof(startup)); 1826 startup.cb = sizeof(startup); 1827 startup.dwFlags = STARTF_USESHOWWINDOW; 1828 startup.wShowWindow = SW_SHOWNORMAL; 1829 CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0L, NULL, NULL, 1830 &startup, &info); 1831 ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, 1832 "child process termination\n"); 1833 } 1834 } 1835 else skip("RegQueryValueExA(key, Favorites, ...) failed\n"); 1836 if (key) 1837 RegCloseKey(key); 1838 } 1839 else skip("RegOpenKeyExA(HKEY_CURRENT_USER, %s, ...) failed\n", userShellFolders); 1840 } 1841 1842 static void test_SHGetFolderPathEx(void) 1843 { 1844 WCHAR buffer[MAX_PATH], *path, *path2; 1845 unsigned int i; 1846 HRESULT hr; 1847 DWORD len; 1848 1849 if (!pSHGetKnownFolderPath || !pSHGetFolderPathEx) 1850 { 1851 win_skip("SHGetKnownFolderPath or SHGetFolderPathEx not available\n"); 1852 return; 1853 } 1854 1855 if (0) { /* crashes */ 1856 hr = pSHGetKnownFolderPath(&FOLDERID_Desktop, 0, NULL, NULL); 1857 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr); 1858 } 1859 /* non-existent folder id */ 1860 path = (void *)0xdeadbeef; 1861 hr = pSHGetKnownFolderPath(&IID_IOleObject, 0, NULL, &path); 1862 ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "got 0x%08x\n", hr); 1863 ok(path == NULL, "got %p\n", path); 1864 1865 path = NULL; 1866 hr = pSHGetKnownFolderPath(&FOLDERID_Desktop, KF_FLAG_DEFAULT_PATH, NULL, &path); 1867 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); 1868 ok(path != NULL, "expected path != NULL\n"); 1869 CoTaskMemFree(path); 1870 1871 for (i = 0; i < ARRAY_SIZE(known_folders); ++i) 1872 { 1873 const KNOWNFOLDERID *folder_id = known_folders[i].folderId; 1874 1875 path = NULL; 1876 hr = pSHGetKnownFolderPath(folder_id, KF_FLAG_DEFAULT, NULL, &path); 1877 if (FAILED(hr)) 1878 continue; 1879 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); 1880 ok(path != NULL, "expected path != NULL\n"); 1881 1882 path2 = NULL; 1883 hr = pSHGetKnownFolderPath(folder_id, KF_FLAG_SIMPLE_IDLIST, NULL, &path2); 1884 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); 1885 ok(path2 != NULL, "expected path != NULL\n"); 1886 ok(!lstrcmpiW(path, path2), "expected equal paths: %s, %s\n", wine_dbgstr_w(path), wine_dbgstr_w(path2)); 1887 CoTaskMemFree(path2); 1888 1889 path2 = NULL; 1890 hr = pSHGetKnownFolderPath(folder_id, KF_FLAG_DONT_UNEXPAND, NULL, &path2); 1891 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); 1892 ok(path2 != NULL, "expected path != NULL\n"); 1893 ok(!lstrcmpiW(path, path2), "expected equal paths: %s, %s\n", wine_dbgstr_w(path), wine_dbgstr_w(path2)); 1894 CoTaskMemFree(path2); 1895 1896 path2 = NULL; 1897 hr = pSHGetKnownFolderPath(folder_id, KF_FLAG_SIMPLE_IDLIST | KF_FLAG_DONT_UNEXPAND, NULL, &path2); 1898 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); 1899 ok(path2 != NULL, "expected path != NULL\n"); 1900 ok(!lstrcmpiW(path, path2), "expected equal paths: %s, %s\n", wine_dbgstr_w(path), wine_dbgstr_w(path2)); 1901 CoTaskMemFree(path2); 1902 1903 CoTaskMemFree(path); 1904 } 1905 1906 path = NULL; 1907 hr = pSHGetKnownFolderPath(&FOLDERID_Desktop, 0, NULL, &path); 1908 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); 1909 ok(path != NULL, "expected path != NULL\n"); 1910 1911 hr = pSHGetFolderPathEx(&FOLDERID_Desktop, 0, NULL, buffer, MAX_PATH); 1912 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); 1913 ok(!lstrcmpiW(path, buffer), "expected equal paths\n"); 1914 len = lstrlenW(buffer); 1915 CoTaskMemFree(path); 1916 1917 hr = pSHGetFolderPathEx(&FOLDERID_Desktop, 0, NULL, buffer, 0); 1918 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr); 1919 1920 if (0) { /* crashes */ 1921 hr = pSHGetFolderPathEx(&FOLDERID_Desktop, 0, NULL, NULL, len + 1); 1922 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr); 1923 1924 hr = pSHGetFolderPathEx(NULL, 0, NULL, buffer, MAX_PATH); 1925 ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr); 1926 } 1927 hr = pSHGetFolderPathEx(&FOLDERID_Desktop, 0, NULL, buffer, len); 1928 ok(hr == E_NOT_SUFFICIENT_BUFFER, "expected E_NOT_SUFFICIENT_BUFFER, got 0x%08x\n", hr); 1929 1930 hr = pSHGetFolderPathEx(&FOLDERID_Desktop, 0, NULL, buffer, len + 1); 1931 ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); 1932 } 1933 1934 static BOOL is_in_strarray(const WCHAR *needle, const char *hay) 1935 { 1936 WCHAR wstr[MAX_PATH]; 1937 1938 if(!needle && !hay) 1939 return TRUE; 1940 1941 while(hay && *hay) 1942 { 1943 DWORD ret; 1944 1945 if(strcmp(hay, "(null)") == 0 && !needle) 1946 return TRUE; 1947 1948 ret = MultiByteToWideChar(CP_ACP, 0, hay, -1, wstr, ARRAY_SIZE(wstr)); 1949 if(ret == 0) 1950 { 1951 ok(0, "Failed to convert string\n"); 1952 return FALSE; 1953 } 1954 1955 if(lstrcmpW(wstr, needle) == 0) 1956 return TRUE; 1957 1958 hay += strlen(hay) + 1; 1959 } 1960 1961 return FALSE; 1962 } 1963 1964 static void check_known_folder(IKnownFolderManager *mgr, KNOWNFOLDERID *folderId) 1965 { 1966 HRESULT hr; 1967 int csidl, expectedCsidl, ret; 1968 KNOWNFOLDER_DEFINITION kfd; 1969 IKnownFolder *folder; 1970 WCHAR sName[1024]; 1971 BOOL found = FALSE; 1972 unsigned int i; 1973 1974 for (i = 0; i < ARRAY_SIZE(known_folders); ++i) 1975 { 1976 const struct knownFolderDef *known_folder = &known_folders[i]; 1977 1978 if(IsEqualGUID(known_folder->folderId, folderId)) 1979 { 1980 known_folder_found[i] = TRUE; 1981 found = TRUE; 1982 /* verify CSIDL */ 1983 if(!(known_folder->csidl & NO_CSIDL)) 1984 { 1985 /* mask off winetest flags */ 1986 expectedCsidl = known_folder->csidl & 0xFFFF; 1987 1988 hr = IKnownFolderManager_FolderIdToCsidl(mgr, folderId, &csidl); 1989 ok_(__FILE__, known_folder->line)(hr == S_OK, "cannot retrieve CSIDL for folder %s\n", known_folder->sFolderId); 1990 1991 ok_(__FILE__, known_folder->line)(csidl == expectedCsidl, "invalid CSIDL retrieved for folder %s. %d (%s) expected, but %d found\n", known_folder->sFolderId, expectedCsidl, known_folder->sCsidl, csidl); 1992 } 1993 1994 hr = IKnownFolderManager_GetFolder(mgr, folderId, &folder); 1995 ok_(__FILE__, known_folder->line)(hr == S_OK, "cannot get known folder for %s\n", known_folder->sFolderId); 1996 if(SUCCEEDED(hr)) 1997 { 1998 hr = IKnownFolder_GetFolderDefinition(folder, &kfd); 1999 ok_(__FILE__, known_folder->line)(hr == S_OK, "cannot get known folder definition for %s\n", known_folder->sFolderId); 2000 if(SUCCEEDED(hr)) 2001 { 2002 ret = MultiByteToWideChar(CP_ACP, 0, known_folder->sName, -1, sName, ARRAY_SIZE(sName)); 2003 ok_(__FILE__, known_folder->line)(ret != 0, "cannot convert known folder name \"%s\" to wide characters\n", known_folder->sName); 2004 2005 ok_(__FILE__, known_folder->line)(lstrcmpW(kfd.pszName, sName)==0, "invalid known folder name returned for %s: %s expected, but %s retrieved\n", known_folder->sFolderId, wine_dbgstr_w(sName), wine_dbgstr_w(kfd.pszName)); 2006 2007 ok_(__FILE__, known_folder->line)(kfd.category == known_folder->category, "invalid known folder category for %s: %d expected, but %d retrieved\n", known_folder->sFolderId, known_folder->category, kfd.category); 2008 2009 ok_(__FILE__, known_folder->line)(IsEqualGUID(known_folder->fidParents[0], &kfd.fidParent) || 2010 IsEqualGUID(known_folder->fidParents[1], &kfd.fidParent), 2011 "invalid known folder parent for %s: %s retrieved\n", 2012 known_folder->sFolderId, wine_dbgstr_guid(&kfd.fidParent)); 2013 2014 ok_(__FILE__, known_folder->line)(is_in_strarray(kfd.pszRelativePath, known_folder->sRelativePath), "invalid known folder relative path returned for %s: %s expected, but %s retrieved\n", known_folder->sFolderId, known_folder->sRelativePath, wine_dbgstr_w(kfd.pszRelativePath)); 2015 2016 ok_(__FILE__, known_folder->line)(is_in_strarray(kfd.pszParsingName, known_folder->sParsingName), "invalid known folder parsing name returned for %s: %s retrieved\n", known_folder->sFolderId, wine_dbgstr_w(kfd.pszParsingName)); 2017 2018 ok_(__FILE__, known_folder->line)(known_folder->attributes == kfd.dwAttributes || 2019 (known_folder->csidl & WINE_ATTRIBUTES_OPTIONAL && kfd.dwAttributes == 0), 2020 "invalid known folder attributes for %s: 0x%08x expected, but 0x%08x retrieved\n", known_folder->sFolderId, known_folder->attributes, kfd.dwAttributes); 2021 2022 ok_(__FILE__, known_folder->line)(!(kfd.kfdFlags & (~known_folder->definitionFlags)), "invalid known folder flags for %s: 0x%08x expected, but 0x%08x retrieved\n", known_folder->sFolderId, known_folder->definitionFlags, kfd.kfdFlags); 2023 2024 FreeKnownFolderDefinitionFields(&kfd); 2025 } 2026 2027 IKnownFolder_Release(folder); 2028 } 2029 2030 break; 2031 } 2032 } 2033 2034 if(!found) 2035 { 2036 trace("unknown known folder found: %s\n", wine_dbgstr_guid(folderId)); 2037 2038 hr = IKnownFolderManager_GetFolder(mgr, folderId, &folder); 2039 ok(hr == S_OK, "cannot get known folder for %s\n", wine_dbgstr_guid(folderId)); 2040 if(SUCCEEDED(hr)) 2041 { 2042 hr = IKnownFolder_GetFolderDefinition(folder, &kfd); 2043 todo_wine 2044 ok(hr == S_OK, "cannot get known folder definition for %s\n", wine_dbgstr_guid(folderId)); 2045 if(SUCCEEDED(hr)) 2046 { 2047 trace(" category: %d\n", kfd.category); 2048 trace(" name: %s\n", wine_dbgstr_w(kfd.pszName)); 2049 trace(" description: %s\n", wine_dbgstr_w(kfd.pszDescription)); 2050 trace(" parent: %s\n", wine_dbgstr_guid(&kfd.fidParent)); 2051 trace(" relative path: %s\n", wine_dbgstr_w(kfd.pszRelativePath)); 2052 trace(" parsing name: %s\n", wine_dbgstr_w(kfd.pszParsingName)); 2053 trace(" tooltip: %s\n", wine_dbgstr_w(kfd.pszTooltip)); 2054 trace(" localized name: %s\n", wine_dbgstr_w(kfd.pszLocalizedName)); 2055 trace(" icon: %s\n", wine_dbgstr_w(kfd.pszIcon)); 2056 trace(" security: %s\n", wine_dbgstr_w(kfd.pszSecurity)); 2057 trace(" attributes: 0x%08x\n", kfd.dwAttributes); 2058 trace(" flags: 0x%08x\n", kfd.kfdFlags); 2059 trace(" type: %s\n", wine_dbgstr_guid(&kfd.ftidType)); 2060 FreeKnownFolderDefinitionFields(&kfd); 2061 } 2062 2063 IKnownFolder_Release(folder); 2064 } 2065 } 2066 } 2067 #undef NO_CSIDL 2068 2069 static void test_knownFolders(void) 2070 { 2071 static const WCHAR sWindows[] = {'W','i','n','d','o','w','s',0}; 2072 static const WCHAR sWindows2[] = {'w','i','n','d','o','w','s',0}; 2073 static const WCHAR sExample[] = {'E','x','a','m','p','l','e',0}; 2074 static const WCHAR sExample2[] = {'E','x','a','m','p','l','e','2',0}; 2075 static const WCHAR sSubFolder[] = {'S','u','b','F','o','l','d','e','r',0}; 2076 static const WCHAR sNoSuch[] = {'N','o','S','u','c','h',0}; 2077 static const WCHAR sBackslash[] = {'\\',0}; 2078 static const KNOWNFOLDERID newFolderId = {0x01234567, 0x89AB, 0xCDEF, {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x01} }; 2079 static const KNOWNFOLDERID subFolderId = {0xFEDCBA98, 0x7654, 0x3210, {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF} }; 2080 HRESULT hr; 2081 IKnownFolderManager *mgr = NULL; 2082 IKnownFolder *folder = NULL, *subFolder = NULL; 2083 KNOWNFOLDERID folderId, *folders; 2084 KF_CATEGORY cat = 0; 2085 KNOWNFOLDER_DEFINITION kfDefinition, kfSubDefinition; 2086 int csidl, i; 2087 UINT nCount = 0; 2088 LPWSTR folderPath, errorMsg; 2089 KF_REDIRECTION_CAPABILITIES redirectionCapabilities = 1; 2090 WCHAR sWinDir[MAX_PATH], sExamplePath[MAX_PATH], sExample2Path[MAX_PATH], sSubFolderPath[MAX_PATH], sSubFolder2Path[MAX_PATH]; 2091 BOOL bRes; 2092 DWORD dwAttributes; 2093 2094 GetWindowsDirectoryW( sWinDir, MAX_PATH ); 2095 2096 GetTempPathW(ARRAY_SIZE(sExamplePath), sExamplePath); 2097 lstrcatW(sExamplePath, sExample); 2098 2099 GetTempPathW(ARRAY_SIZE(sExample2Path), sExample2Path); 2100 lstrcatW(sExample2Path, sExample2); 2101 2102 lstrcpyW(sSubFolderPath, sExamplePath); 2103 lstrcatW(sSubFolderPath, sBackslash); 2104 lstrcatW(sSubFolderPath, sSubFolder); 2105 2106 lstrcpyW(sSubFolder2Path, sExample2Path); 2107 lstrcatW(sSubFolder2Path, sBackslash); 2108 lstrcatW(sSubFolder2Path, sSubFolder); 2109 2110 CoInitialize(NULL); 2111 2112 hr = CoCreateInstance(&CLSID_KnownFolderManager, NULL, CLSCTX_INPROC_SERVER, 2113 &IID_IKnownFolderManager, (LPVOID*)&mgr); 2114 if(hr == REGDB_E_CLASSNOTREG) 2115 win_skip("IKnownFolderManager unavailable\n"); 2116 else 2117 { 2118 IUnknown *unk; 2119 2120 ok(hr == S_OK, "failed to create KnownFolderManager instance: 0x%08x\n", hr); 2121 2122 hr = IKnownFolderManager_QueryInterface(mgr, &IID_IMarshal, (void**)&unk); 2123 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr); 2124 2125 hr = IKnownFolderManager_FolderIdFromCsidl(mgr, CSIDL_WINDOWS, &folderId); 2126 ok(hr == S_OK, "failed to convert CSIDL to KNOWNFOLDERID: 0x%08x\n", hr); 2127 ok(IsEqualGUID(&folderId, &FOLDERID_Windows)==TRUE, "invalid KNOWNFOLDERID returned\n"); 2128 2129 hr = IKnownFolderManager_FolderIdToCsidl(mgr, &FOLDERID_Windows, &csidl); 2130 ok(hr == S_OK, "failed to convert CSIDL to KNOWNFOLDERID: 0x%08x\n", hr); 2131 ok(csidl == CSIDL_WINDOWS, "invalid CSIDL returned\n"); 2132 2133 hr = IKnownFolderManager_GetFolder(mgr, &FOLDERID_Windows, &folder); 2134 ok(hr == S_OK, "failed to get known folder: 0x%08x\n", hr); 2135 if(SUCCEEDED(hr)) 2136 { 2137 hr = IKnownFolder_QueryInterface(folder, &IID_IMarshal, (void**)&unk); 2138 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr); 2139 2140 hr = IKnownFolder_GetCategory(folder, &cat); 2141 ok(hr == S_OK, "failed to get folder category: 0x%08x\n", hr); 2142 ok(cat==KF_CATEGORY_FIXED, "invalid folder category: %d\n", cat); 2143 2144 hr = IKnownFolder_GetId(folder, &folderId); 2145 ok(hr == S_OK, "failed to get folder id: 0x%08x\n", hr); 2146 ok(IsEqualGUID(&folderId, &FOLDERID_Windows)==TRUE, "invalid KNOWNFOLDERID returned\n"); 2147 2148 hr = IKnownFolder_GetPath(folder, 0, &folderPath); 2149 ok(hr == S_OK, "failed to get path from known folder: 0x%08x\n", hr); 2150 ok(lstrcmpiW(sWinDir, folderPath)==0, "invalid path returned: \"%s\", expected: \"%s\"\n", wine_dbgstr_w(folderPath), wine_dbgstr_w(sWinDir)); 2151 CoTaskMemFree(folderPath); 2152 2153 hr = IKnownFolder_GetRedirectionCapabilities(folder, &redirectionCapabilities); 2154 ok(hr == S_OK, "failed to get redirection capabilities: 0x%08x\n", hr); 2155 todo_wine 2156 ok(redirectionCapabilities==0, "invalid redirection capabilities returned: %d\n", redirectionCapabilities); 2157 2158 hr = IKnownFolder_SetPath(folder, 0, sWinDir); 2159 todo_wine 2160 ok(hr == E_INVALIDARG, "unexpected value from SetPath: 0x%08x\n", hr); 2161 2162 hr = IKnownFolder_GetFolderDefinition(folder, &kfDefinition); 2163 ok(hr == S_OK, "failed to get folder definition: 0x%08x\n", hr); 2164 if(SUCCEEDED(hr)) 2165 { 2166 ok(kfDefinition.category==KF_CATEGORY_FIXED, "invalid folder category: 0x%08x\n", kfDefinition.category); 2167 ok(lstrcmpW(kfDefinition.pszName, sWindows)==0, "invalid folder name: %s\n", wine_dbgstr_w(kfDefinition.pszName)); 2168 ok(kfDefinition.dwAttributes==0, "invalid folder attributes: %d\n", kfDefinition.dwAttributes); 2169 FreeKnownFolderDefinitionFields(&kfDefinition); 2170 } 2171 2172 hr = IKnownFolder_Release(folder); 2173 ok(hr == S_OK, "failed to release KnownFolder instance: 0x%08x\n", hr); 2174 } 2175 2176 hr = IKnownFolderManager_GetFolderByName(mgr, sWindows, &folder); 2177 ok(hr == S_OK, "failed to get known folder: 0x%08x\n", hr); 2178 if(SUCCEEDED(hr)) 2179 { 2180 hr = IKnownFolder_GetId(folder, &folderId); 2181 ok(hr == S_OK, "failed to get folder id: 0x%08x\n", hr); 2182 ok(IsEqualGUID(&folderId, &FOLDERID_Windows)==TRUE, "invalid KNOWNFOLDERID returned\n"); 2183 2184 hr = IKnownFolder_Release(folder); 2185 ok(hr == S_OK, "failed to release KnownFolder instance: 0x%08x\n", hr); 2186 } 2187 2188 hr = IKnownFolderManager_GetFolderByName(mgr, sWindows2, &folder); 2189 ok(hr == S_OK, "failed to get known folder: 0x%08x\n", hr); 2190 if(SUCCEEDED(hr)) 2191 { 2192 hr = IKnownFolder_GetId(folder, &folderId); 2193 ok(hr == S_OK, "failed to get folder id: 0x%08x\n", hr); 2194 ok(IsEqualGUID(&folderId, &FOLDERID_Windows)==TRUE, "invalid KNOWNFOLDERID returned\n"); 2195 2196 hr = IKnownFolder_Release(folder); 2197 ok(hr == S_OK, "failed to release KnownFolder instance: 0x%08x\n", hr); 2198 } 2199 2200 folder = (IKnownFolder *)0xdeadbeef; 2201 hr = IKnownFolderManager_GetFolderByName(mgr, sNoSuch, &folder); 2202 ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "got 0x%08x\n", hr); 2203 ok(folder == NULL, "got %p\n", folder); 2204 2205 for(i=0; i < ARRAY_SIZE(known_folder_found); ++i) 2206 known_folder_found[i] = FALSE; 2207 2208 hr = IKnownFolderManager_GetFolderIds(mgr, &folders, &nCount); 2209 ok(hr == S_OK, "failed to get known folders: 0x%08x\n", hr); 2210 for(i=0;i<nCount;++i) 2211 check_known_folder(mgr, &folders[i]); 2212 2213 for(i=0; i < ARRAY_SIZE(known_folder_found); ++i) 2214 if(!known_folder_found[i]) 2215 trace("Known folder %s not found on current platform\n", known_folders[i].sFolderId); 2216 2217 CoTaskMemFree(folders); 2218 2219 /* test of registering new known folders */ 2220 bRes = CreateDirectoryW(sExamplePath, NULL); 2221 ok(bRes, "cannot create example directory: %s\n", wine_dbgstr_w(sExamplePath)); 2222 bRes = CreateDirectoryW(sExample2Path, NULL); 2223 ok(bRes, "cannot create example directory: %s\n", wine_dbgstr_w(sExample2Path)); 2224 bRes = CreateDirectoryW(sSubFolderPath, NULL); 2225 ok(bRes, "cannot create example directory: %s\n", wine_dbgstr_w(sSubFolderPath)); 2226 2227 ZeroMemory(&kfDefinition, sizeof(kfDefinition)); 2228 kfDefinition.category = KF_CATEGORY_PERUSER; 2229 kfDefinition.pszName = CoTaskMemAlloc(sizeof(sExample)); 2230 lstrcpyW(kfDefinition.pszName, sExample); 2231 kfDefinition.pszDescription = CoTaskMemAlloc(sizeof(sExample)); 2232 lstrcpyW(kfDefinition.pszDescription, sExample); 2233 kfDefinition.pszRelativePath = CoTaskMemAlloc(sizeof(sExamplePath)); 2234 lstrcpyW(kfDefinition.pszRelativePath, sExamplePath); 2235 2236 hr = IKnownFolderManager_RegisterFolder(mgr, &newFolderId, &kfDefinition); 2237 if(hr == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED)) 2238 win_skip("No permissions required to register custom known folder\n"); 2239 else 2240 { 2241 ok(hr == S_OK, "failed to register known folder: 0x%08x\n", hr); 2242 if(SUCCEEDED(hr)) 2243 { 2244 hr = IKnownFolderManager_GetFolder(mgr, &newFolderId, &folder); 2245 ok(hr == S_OK, "failed to get known folder: 0x%08x\n", hr); 2246 if(SUCCEEDED(hr)) 2247 { 2248 hr = IKnownFolder_GetCategory(folder, &cat); 2249 ok(hr == S_OK, "failed to get folder category: hr=0x%0x\n", hr); 2250 ok(cat == KF_CATEGORY_PERUSER, "invalid category returned: %d, while %d (KF_CATEGORY_PERUSER) expected\n", cat, KF_CATEGORY_PERUSER); 2251 2252 hr = IKnownFolder_GetId(folder, &folderId); 2253 ok(hr == S_OK, "failed to get folder id: 0x%08x\n", hr); 2254 ok(IsEqualGUID(&folderId, &newFolderId)==TRUE, "invalid KNOWNFOLDERID returned\n"); 2255 2256 /* current path should be Temp\Example */ 2257 hr = IKnownFolder_GetPath(folder, 0, &folderPath); 2258 ok(hr == S_OK, "failed to get path from known folder: 0x%08x\n", hr); 2259 ok(lstrcmpiW(folderPath, sExamplePath)==0, "invalid known folder path retrieved: \"%s\" when \"%s\" was expected\n", wine_dbgstr_w(folderPath), wine_dbgstr_w(sExamplePath)); 2260 CoTaskMemFree(folderPath); 2261 2262 /* register sub-folder and mark it as child of Example folder */ 2263 ZeroMemory(&kfSubDefinition, sizeof(kfSubDefinition)); 2264 kfSubDefinition.category = KF_CATEGORY_PERUSER; 2265 kfSubDefinition.pszName = CoTaskMemAlloc(sizeof(sSubFolder)); 2266 lstrcpyW(kfSubDefinition.pszName, sSubFolder); 2267 kfSubDefinition.pszDescription = CoTaskMemAlloc(sizeof(sSubFolder)); 2268 lstrcpyW(kfSubDefinition.pszDescription, sSubFolder); 2269 kfSubDefinition.pszRelativePath = CoTaskMemAlloc(sizeof(sSubFolder)); 2270 lstrcpyW(kfSubDefinition.pszRelativePath, sSubFolder); 2271 kfSubDefinition.fidParent = newFolderId; 2272 2273 hr = IKnownFolderManager_RegisterFolder(mgr, &subFolderId, &kfSubDefinition); 2274 ok(hr == S_OK, "failed to register known folder: 0x%08x\n", hr); 2275 if(SUCCEEDED(hr)) 2276 { 2277 2278 hr = IKnownFolderManager_GetFolder(mgr, &subFolderId, &subFolder); 2279 ok(hr == S_OK, "failed to get known folder: 0x%08x\n", hr); 2280 if(SUCCEEDED(hr)) 2281 { 2282 /* check sub folder path */ 2283 hr = IKnownFolder_GetPath(subFolder, 0, &folderPath); 2284 ok(hr == S_OK, "failed to get known folder path: 0x%08x\n", hr); 2285 ok(lstrcmpiW(folderPath, sSubFolderPath)==0, "invalid known folder path retrieved: \"%s\" when \"%s\" was expected\n", wine_dbgstr_w(folderPath), wine_dbgstr_w(sSubFolderPath)); 2286 CoTaskMemFree(folderPath); 2287 2288 2289 /* try to redirect Example to Temp\Example2 */ 2290 hr = IKnownFolderManager_Redirect(mgr, &newFolderId, NULL, 0, sExample2Path, 0, NULL, &errorMsg); 2291 ok(hr == S_OK, "failed to redirect known folder: 0x%08x, errorMsg: %s\n", hr, wine_dbgstr_w(errorMsg)); 2292 2293 /* verify */ 2294 hr = IKnownFolder_GetPath(folder, 0, &folderPath); 2295 ok(hr == S_OK, "failed to get known folder path: 0x%08x\n", hr); 2296 ok(lstrcmpiW(folderPath, sExample2Path)==0, "invalid known folder path retrieved: \"%s\" when \"%s\" was expected\n", wine_dbgstr_w(folderPath), wine_dbgstr_w(sExample2Path)); 2297 CoTaskMemFree(folderPath); 2298 2299 /* verify sub folder - it should fail now, as we redirected its parent folder, but we have no sub folder in new location */ 2300 hr = IKnownFolder_GetPath(subFolder, 0, &folderPath); 2301 ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "unexpected value from GetPath(): 0x%08x\n", hr); 2302 ok(folderPath==NULL, "invalid known folder path retrieved: \"%s\" when NULL pointer was expected\n", wine_dbgstr_w(folderPath)); 2303 CoTaskMemFree(folderPath); 2304 2305 2306 /* set Example path to original. Using SetPath() is valid here, as it also uses redirection internally */ 2307 hr = IKnownFolder_SetPath(folder, 0, sExamplePath); 2308 ok(hr == S_OK, "SetPath() failed: 0x%08x\n", hr); 2309 2310 /* verify */ 2311 hr = IKnownFolder_GetPath(folder, 0, &folderPath); 2312 ok(hr == S_OK, "failed to get known folder path: 0x%08x\n", hr); 2313 ok(lstrcmpiW(folderPath, sExamplePath)==0, "invalid known folder path retrieved: \"%s\" when \"%s\" was expected\n", wine_dbgstr_w(folderPath), wine_dbgstr_w(sExamplePath)); 2314 CoTaskMemFree(folderPath); 2315 2316 2317 /* create sub folder in Temp\Example2 */ 2318 bRes = CreateDirectoryW(sSubFolder2Path, NULL); 2319 ok(bRes, "cannot create example directory: %s\n", wine_dbgstr_w(sSubFolder2Path)); 2320 2321 /* again perform that same redirection */ 2322 hr = IKnownFolderManager_Redirect(mgr, &newFolderId, NULL, 0, sExample2Path, 0, NULL, &errorMsg); 2323 ok(hr == S_OK, "failed to redirect known folder: 0x%08x, errorMsg: %s\n", hr, wine_dbgstr_w(errorMsg)); 2324 2325 /* verify sub folder. It should succeed now, as the required sub folder exists */ 2326 hr = IKnownFolder_GetPath(subFolder, 0, &folderPath); 2327 ok(hr == S_OK, "failed to get known folder path: 0x%08x\n", hr); 2328 ok(lstrcmpiW(folderPath, sSubFolder2Path)==0, "invalid known folder path retrieved: \"%s\" when \"%s\" was expected\n", wine_dbgstr_w(folderPath), wine_dbgstr_w(sSubFolder2Path)); 2329 CoTaskMemFree(folderPath); 2330 2331 /* remove newly created directory */ 2332 RemoveDirectoryW(sSubFolder2Path); 2333 2334 /* verify subfolder. It still succeeds, so Windows does not check folder presence each time */ 2335 hr = IKnownFolder_GetPath(subFolder, 0, &folderPath); 2336 todo_wine 2337 ok(hr == S_OK, "failed to get known folder path: 0x%08x\n", hr); 2338 todo_wine 2339 ok(lstrcmpiW(folderPath, sSubFolder2Path)==0, "invalid known folder path retrieved: \"%s\" when \"%s\" was expected\n", wine_dbgstr_w(folderPath), wine_dbgstr_w(sSubFolder2Path)); 2340 CoTaskMemFree(folderPath); 2341 2342 2343 /* set Example path to original */ 2344 hr = IKnownFolder_SetPath(folder, 0, sExamplePath); 2345 ok(hr == S_OK, "SetPath() failed: 0x%08x\n", hr); 2346 2347 /* verify */ 2348 hr = IKnownFolder_GetPath(folder, 0, &folderPath); 2349 ok(hr == S_OK, "failed to get known folder path: 0x%08x\n", hr); 2350 ok(lstrcmpiW(folderPath, sExamplePath)==0, "invalid known folder path retrieved: \"%s\" when \"%s\" was expected\n", wine_dbgstr_w(folderPath), wine_dbgstr_w(sExamplePath)); 2351 CoTaskMemFree(folderPath); 2352 2353 /* verify sub folder */ 2354 hr = IKnownFolder_GetPath(subFolder, 0, &folderPath); 2355 ok(hr == S_OK, "failed to get known folder path: 0x%08x\n", hr); 2356 ok(lstrcmpiW(folderPath, sSubFolderPath)==0, "invalid known folder path retrieved: \"%s\" when \"%s\" was expected\n", wine_dbgstr_w(folderPath), wine_dbgstr_w(sSubFolderPath)); 2357 CoTaskMemFree(folderPath); 2358 2359 2360 /* create sub folder in Temp\Example2 */ 2361 bRes = CreateDirectoryW(sSubFolder2Path, NULL); 2362 ok(bRes, "cannot create example directory: %s\n", wine_dbgstr_w(sSubFolder2Path)); 2363 2364 /* do that same redirection, but try to exclude sub-folder */ 2365 hr = IKnownFolderManager_Redirect(mgr, &newFolderId, NULL, 0, sExample2Path, 1, &subFolderId, &errorMsg); 2366 ok(hr == S_OK, "failed to redirect known folder: 0x%08x, errorMsg: %s\n", hr, wine_dbgstr_w(errorMsg)); 2367 2368 /* verify */ 2369 hr = IKnownFolder_GetPath(folder, 0, &folderPath); 2370 ok(hr == S_OK, "failed to get known folder path: 0x%08x\n", hr); 2371 ok(lstrcmpiW(folderPath, sExample2Path)==0, "invalid known folder path retrieved: \"%s\" when \"%s\" was expected\n", wine_dbgstr_w(folderPath), wine_dbgstr_w(sExample2Path)); 2372 CoTaskMemFree(folderPath); 2373 2374 /* verify sub folder. Unexpectedly, this path was also changed. So, exclusion seems to be ignored (Windows bug)? This test however will let us know, if this behavior is changed */ 2375 hr = IKnownFolder_GetPath(subFolder, 0, &folderPath); 2376 ok(hr == S_OK, "failed to get known folder path: 0x%08x\n", hr); 2377 ok(lstrcmpiW(folderPath, sSubFolder2Path)==0, "invalid known folder path retrieved: \"%s\" when \"%s\" was expected\n", wine_dbgstr_w(folderPath), wine_dbgstr_w(sSubFolder2Path)); 2378 CoTaskMemFree(folderPath); 2379 2380 /* remove newly created directory */ 2381 RemoveDirectoryW(sSubFolder2Path); 2382 2383 2384 /* set Example path to original */ 2385 hr = IKnownFolder_SetPath(folder, 0, sExamplePath); 2386 ok(hr == S_OK, "SetPath() failed: 0x%08x\n", hr); 2387 2388 /* verify */ 2389 hr = IKnownFolder_GetPath(folder, 0, &folderPath); 2390 ok(hr == S_OK, "failed to get known folder path: 0x%08x\n", hr); 2391 ok(lstrcmpiW(folderPath, sExamplePath)==0, "invalid known folder path retrieved: \"%s\" when \"%s\" was expected\n", wine_dbgstr_w(folderPath), wine_dbgstr_w(sExamplePath)); 2392 CoTaskMemFree(folderPath); 2393 2394 /* verify sub folder */ 2395 hr = IKnownFolder_GetPath(subFolder, 0, &folderPath); 2396 ok(hr == S_OK, "failed to get known folder path: 0x%08x\n", hr); 2397 ok(lstrcmpiW(folderPath, sSubFolderPath)==0, "invalid known folder path retrieved: \"%s\" when \"%s\" was expected\n", wine_dbgstr_w(folderPath), wine_dbgstr_w(sSubFolderPath)); 2398 CoTaskMemFree(folderPath); 2399 2400 2401 /* do that same redirection again, but set it to copy content. It should also copy the sub folder, so checking it would succeed now */ 2402 hr = IKnownFolderManager_Redirect(mgr, &newFolderId, NULL, KF_REDIRECT_COPY_CONTENTS, sExample2Path, 0, NULL, &errorMsg); 2403 ok(hr == S_OK, "failed to redirect known folder: 0x%08x, errorMsg: %s\n", hr, wine_dbgstr_w(errorMsg)); 2404 2405 /* verify */ 2406 hr = IKnownFolder_GetPath(folder, 0, &folderPath); 2407 ok(hr == S_OK, "failed to get known folder path: 0x%08x\n", hr); 2408 ok(lstrcmpiW(folderPath, sExample2Path)==0, "invalid known folder path retrieved: \"%s\" when \"%s\" was expected\n", wine_dbgstr_w(folderPath), wine_dbgstr_w(sExample2Path)); 2409 CoTaskMemFree(folderPath); 2410 2411 /* verify sub folder */ 2412 hr = IKnownFolder_GetPath(subFolder, 0, &folderPath); 2413 ok(hr == S_OK, "failed to get known folder path: 0x%08x\n", hr); 2414 ok(lstrcmpiW(folderPath, sSubFolder2Path)==0, "invalid known folder path retrieved: \"%s\" when \"%s\" was expected\n", wine_dbgstr_w(folderPath), wine_dbgstr_w(sSubFolder2Path)); 2415 CoTaskMemFree(folderPath); 2416 2417 /* remove copied directory */ 2418 RemoveDirectoryW(sSubFolder2Path); 2419 2420 2421 /* set Example path to original */ 2422 hr = IKnownFolder_SetPath(folder, 0, sExamplePath); 2423 ok(hr == S_OK, "SetPath() failed: 0x%08x\n", hr); 2424 2425 /* verify */ 2426 hr = IKnownFolder_GetPath(folder, 0, &folderPath); 2427 ok(hr == S_OK, "failed to get known folder path: 0x%08x\n", hr); 2428 ok(lstrcmpiW(folderPath, sExamplePath)==0, "invalid known folder path retrieved: \"%s\" when \"%s\" was expected\n", wine_dbgstr_w(folderPath), wine_dbgstr_w(sExamplePath)); 2429 CoTaskMemFree(folderPath); 2430 2431 /* verify sub folder */ 2432 hr = IKnownFolder_GetPath(subFolder, 0, &folderPath); 2433 ok(hr == S_OK, "failed to get known folder path: 0x%08x\n", hr); 2434 ok(lstrcmpiW(folderPath, sSubFolderPath)==0, "invalid known folder path retrieved: \"%s\" when \"%s\" was expected\n", wine_dbgstr_w(folderPath), wine_dbgstr_w(sSubFolderPath)); 2435 CoTaskMemFree(folderPath); 2436 2437 2438 /* redirect again, set it to copy content and remove originals */ 2439 hr = IKnownFolderManager_Redirect(mgr, &newFolderId, NULL, KF_REDIRECT_COPY_CONTENTS | KF_REDIRECT_DEL_SOURCE_CONTENTS, sExample2Path, 0, NULL, &errorMsg); 2440 ok(hr == S_OK, "failed to redirect known folder: 0x%08x, errorMsg: %s\n", hr, wine_dbgstr_w(errorMsg)); 2441 2442 /* verify */ 2443 hr = IKnownFolder_GetPath(folder, 0, &folderPath); 2444 ok(hr == S_OK, "failed to get known folder path: 0x%08x\n", hr); 2445 ok(lstrcmpiW(folderPath, sExample2Path)==0, "invalid known folder path retrieved: \"%s\" when \"%s\" was expected\n", wine_dbgstr_w(folderPath), wine_dbgstr_w(sExample2Path)); 2446 CoTaskMemFree(folderPath); 2447 2448 /* verify sub folder */ 2449 hr = IKnownFolder_GetPath(subFolder, 0, &folderPath); 2450 ok(hr == S_OK, "failed to get known folder path: 0x%08x\n", hr); 2451 ok(lstrcmpiW(folderPath, sSubFolder2Path)==0, "invalid known folder path retrieved: \"%s\" when \"%s\" was expected\n", wine_dbgstr_w(folderPath), wine_dbgstr_w(sSubFolder2Path)); 2452 CoTaskMemFree(folderPath); 2453 2454 /* check if original directory was really removed */ 2455 dwAttributes = GetFileAttributesW(sExamplePath); 2456 ok(dwAttributes==INVALID_FILE_ATTRIBUTES, "directory should not exist, but has attributes: 0x%08x\n", dwAttributes ); 2457 2458 2459 /* redirect (with copy) to original path */ 2460 hr = IKnownFolderManager_Redirect(mgr, &newFolderId, NULL, KF_REDIRECT_COPY_CONTENTS, sExamplePath, 0, NULL, &errorMsg); 2461 ok(hr == S_OK, "failed to redirect known folder: 0x%08x, errorMsg: %s\n", hr, wine_dbgstr_w(errorMsg)); 2462 2463 /* verify */ 2464 hr = IKnownFolder_GetPath(folder, 0, &folderPath); 2465 ok(hr == S_OK, "failed to get known folder path: 0x%08x\n", hr); 2466 ok(lstrcmpiW(folderPath, sExamplePath)==0, "invalid known folder path retrieved: \"%s\" when \"%s\" was expected\n", wine_dbgstr_w(folderPath), wine_dbgstr_w(sExamplePath)); 2467 CoTaskMemFree(folderPath); 2468 2469 /* verify sub folder */ 2470 hr = IKnownFolder_GetPath(subFolder, 0, &folderPath); 2471 ok(hr == S_OK, "failed to get known folder path: 0x%08x\n", hr); 2472 ok(lstrcmpiW(folderPath, sSubFolderPath)==0, "invalid known folder path retrieved: \"%s\" when \"%s\" was expected\n", wine_dbgstr_w(folderPath), wine_dbgstr_w(sSubFolderPath)); 2473 CoTaskMemFree(folderPath); 2474 2475 /* check shell utility functions */ 2476 if(!pSHGetKnownFolderPath || !pSHSetKnownFolderPath) 2477 todo_wine 2478 win_skip("cannot get SHGet/SetKnownFolderPath routines\n"); 2479 else 2480 { 2481 /* try to get current known folder path */ 2482 hr = pSHGetKnownFolderPath(&newFolderId, 0, NULL, &folderPath); 2483 todo_wine 2484 ok(hr==S_OK, "cannot get known folder path: hr=0x%0x\n", hr); 2485 todo_wine 2486 ok(lstrcmpW(folderPath, sExamplePath)==0, "invalid path returned: %s\n", wine_dbgstr_w(folderPath)); 2487 2488 /* set it to new value */ 2489 hr = pSHSetKnownFolderPath(&newFolderId, 0, NULL, sExample2Path); 2490 todo_wine 2491 ok(hr==S_OK, "cannot set known folder path: hr=0x%0x\n", hr); 2492 2493 /* check if it changed */ 2494 hr = pSHGetKnownFolderPath(&newFolderId, 0, NULL, &folderPath); 2495 todo_wine 2496 ok(hr==S_OK, "cannot get known folder path: hr=0x%0x\n", hr); 2497 todo_wine 2498 ok(lstrcmpW(folderPath, sExample2Path)==0, "invalid path returned: %s\n", wine_dbgstr_w(folderPath)); 2499 2500 /* set it back */ 2501 hr = pSHSetKnownFolderPath(&newFolderId, 0, NULL, sExamplePath); 2502 todo_wine 2503 ok(hr==S_OK, "cannot set known folder path: hr=0x%0x\n", hr); 2504 } 2505 2506 IKnownFolder_Release(subFolder); 2507 } 2508 2509 hr = IKnownFolderManager_UnregisterFolder(mgr, &subFolderId); 2510 ok(hr == S_OK, "failed to unregister folder: 0x%08x\n", hr); 2511 } 2512 2513 FreeKnownFolderDefinitionFields(&kfSubDefinition); 2514 2515 hr = IKnownFolder_Release(folder); 2516 ok(hr == S_OK, "failed to release KnownFolder instance: 0x%08x\n", hr); 2517 2518 /* update the folder */ 2519 CoTaskMemFree(kfDefinition.pszName); 2520 kfDefinition.pszName = CoTaskMemAlloc(sizeof(sExample2)); 2521 lstrcpyW(kfDefinition.pszName, sExample2); 2522 hr = IKnownFolderManager_RegisterFolder(mgr, &newFolderId, &kfDefinition); 2523 ok(hr == S_OK, "failed to re-register known folder: 0x%08x\n", hr); 2524 2525 hr = IKnownFolderManager_GetFolder(mgr, &newFolderId, &folder); 2526 ok(hr == S_OK, "failed to get known folder: 0x%08x\n", hr); 2527 2528 hr = IKnownFolder_GetFolderDefinition(folder, &kfSubDefinition); 2529 ok(hr == S_OK, "failed to get folder definition: 0x%08x\n", hr); 2530 ok(!memcmp(kfDefinition.pszName, kfSubDefinition.pszName, sizeof(sExample2)), 2531 "Got wrong updated name: %s\n", wine_dbgstr_w(kfSubDefinition.pszName)); 2532 2533 FreeKnownFolderDefinitionFields(&kfSubDefinition); 2534 2535 hr = IKnownFolder_Release(folder); 2536 ok(hr == S_OK, "failed to release KnownFolder instance: 0x%08x\n", hr); 2537 } 2538 2539 hr = IKnownFolderManager_UnregisterFolder(mgr, &newFolderId); 2540 ok(hr == S_OK, "failed to unregister folder: 0x%08x\n", hr); 2541 } 2542 } 2543 FreeKnownFolderDefinitionFields(&kfDefinition); 2544 2545 RemoveDirectoryW(sSubFolder2Path); 2546 RemoveDirectoryW(sSubFolderPath); 2547 RemoveDirectoryW(sExamplePath); 2548 RemoveDirectoryW(sExample2Path); 2549 2550 hr = IKnownFolderManager_Release(mgr); 2551 ok(hr == S_OK, "failed to release KnownFolderManager instance: 0x%08x\n", hr); 2552 } 2553 CoUninitialize(); 2554 } 2555 2556 2557 static void test_DoEnvironmentSubst(void) 2558 { 2559 WCHAR expectedW[MAX_PATH]; 2560 WCHAR bufferW[MAX_PATH]; 2561 CHAR expectedA[MAX_PATH]; 2562 CHAR bufferA[MAX_PATH]; 2563 DWORD res; 2564 DWORD res2; 2565 DWORD len; 2566 INT i; 2567 static const WCHAR does_not_existW[] = {'%','D','O','E','S','_','N','O','T','_','E','X','I','S','T','%',0}; 2568 static const CHAR does_not_existA[] = "%DOES_NOT_EXIST%"; 2569 static const CHAR *names[] = { 2570 /* interactive apps and services (works on all windows versions) */ 2571 "%ALLUSERSPROFILE%", "%APPDATA%", "%LOCALAPPDATA%", 2572 "%NUMBER_OF_PROCESSORS%", "%OS%", "%PROCESSOR_ARCHITECTURE%", 2573 "%PROCESSOR_IDENTIFIER%", "%PROCESSOR_LEVEL%", "%PROCESSOR_REVISION%", 2574 "%ProgramFiles%", "%SystemDrive%", 2575 "%SystemRoot%", "%USERPROFILE%", "%windir%", 2576 /* todo_wine: "%COMPUTERNAME%", "%ProgramData%", "%PUBLIC%", */ 2577 2578 /* replace more than one var is allowed */ 2579 "%HOMEDRIVE%%HOMEPATH%", 2580 "%OS% %windir%"}; /* always the last entry in the table */ 2581 2582 for (i = 0; i < (ARRAY_SIZE(names)); i++) 2583 { 2584 memset(bufferA, '#', MAX_PATH - 1); 2585 bufferA[MAX_PATH - 1] = 0; 2586 lstrcpyA(bufferA, names[i]); 2587 MultiByteToWideChar(CP_ACP, 0, bufferA, MAX_PATH, bufferW, ARRAY_SIZE(bufferW)); 2588 2589 res2 = ExpandEnvironmentStringsA(names[i], expectedA, MAX_PATH); 2590 res = DoEnvironmentSubstA(bufferA, MAX_PATH); 2591 2592 /* is the space for the terminating 0 included? */ 2593 if (!i && HIWORD(res) && (LOWORD(res) == (lstrlenA(bufferA)))) 2594 { 2595 win_skip("DoEnvironmentSubstA/W are broken on NT 4\n"); 2596 return; 2597 } 2598 ok(HIWORD(res) && (LOWORD(res) == res2), 2599 "%d: got %d/%d (expected TRUE/%d)\n", i, HIWORD(res), LOWORD(res), res2); 2600 ok(!lstrcmpA(bufferA, expectedA), 2601 "%d: got %s (expected %s)\n", i, bufferA, expectedA); 2602 2603 res2 = ExpandEnvironmentStringsW(bufferW, expectedW, MAX_PATH); 2604 res = DoEnvironmentSubstW(bufferW, MAX_PATH); 2605 ok(HIWORD(res) && (LOWORD(res) == res2), 2606 "%d: got %d/%d (expected TRUE/%d)\n", i, HIWORD(res), LOWORD(res), res2); 2607 ok(!lstrcmpW(bufferW, expectedW), 2608 "%d: got %s (expected %s)\n", i, wine_dbgstr_w(bufferW), wine_dbgstr_w(expectedW)); 2609 } 2610 2611 i--; /* reuse data in the last table entry */ 2612 len = LOWORD(res); /* needed length */ 2613 2614 /* one character extra is fine */ 2615 memset(bufferA, '#', MAX_PATH - 1); 2616 bufferA[len + 2] = 0; 2617 lstrcpyA(bufferA, names[i]); 2618 MultiByteToWideChar(CP_ACP, 0, bufferA, MAX_PATH, bufferW, ARRAY_SIZE(bufferW)); 2619 2620 res2 = ExpandEnvironmentStringsA(bufferA, expectedA, MAX_PATH); 2621 res = DoEnvironmentSubstA(bufferA, len + 1); 2622 ok(HIWORD(res) && (LOWORD(res) == res2), 2623 "+1: got %d/%d (expected TRUE/%d)\n", HIWORD(res), LOWORD(res), res2); 2624 ok(!lstrcmpA(bufferA, expectedA), 2625 "+1: got %s (expected %s)\n", bufferA, expectedA); 2626 2627 res2 = ExpandEnvironmentStringsW(bufferW, expectedW, MAX_PATH); 2628 res = DoEnvironmentSubstW(bufferW, len + 1); 2629 ok(HIWORD(res) && (LOWORD(res) == res2), 2630 "+1: got %d/%d (expected TRUE/%d)\n", HIWORD(res), LOWORD(res), res2); 2631 ok(!lstrcmpW(bufferW, expectedW), 2632 "+1: got %s (expected %s)\n", wine_dbgstr_w(bufferW), wine_dbgstr_w(expectedW)); 2633 2634 2635 /* minimal buffer length (result string and terminating 0) */ 2636 memset(bufferA, '#', MAX_PATH - 1); 2637 bufferA[len + 2] = 0; 2638 lstrcpyA(bufferA, names[i]); 2639 MultiByteToWideChar(CP_ACP, 0, bufferA, MAX_PATH, bufferW, ARRAY_SIZE(bufferW)); 2640 2641 /* ANSI version failed without an extra byte, as documented on msdn */ 2642 res = DoEnvironmentSubstA(bufferA, len); 2643 ok(!HIWORD(res) && (LOWORD(res) == len), 2644 " 0: got %d/%d (expected FALSE/%d)\n", HIWORD(res), LOWORD(res), len); 2645 ok(!lstrcmpA(bufferA, names[i]), 2646 " 0: got %s (expected %s)\n", bufferA, names[i]); 2647 2648 /* DoEnvironmentSubstW works as expected */ 2649 res2 = ExpandEnvironmentStringsW(bufferW, expectedW, MAX_PATH); 2650 res = DoEnvironmentSubstW(bufferW, len); 2651 ok(HIWORD(res) && (LOWORD(res) == res2), 2652 " 0: got %d/%d (expected TRUE/%d)\n", HIWORD(res), LOWORD(res), res2); 2653 ok(!lstrcmpW(bufferW, expectedW), 2654 " 0: got %s (expected %s)\n", wine_dbgstr_w(bufferW), wine_dbgstr_w(expectedW)); 2655 2656 2657 /* Buffer too small */ 2658 /* result: FALSE / provided buffer length / the buffer is untouched */ 2659 memset(bufferA, '#', MAX_PATH - 1); 2660 bufferA[len + 2] = 0; 2661 lstrcpyA(bufferA, names[i]); 2662 MultiByteToWideChar(CP_ACP, 0, bufferA, MAX_PATH, bufferW, ARRAY_SIZE(bufferW)); 2663 2664 res = DoEnvironmentSubstA(bufferA, len - 1); 2665 ok(!HIWORD(res) && (LOWORD(res) == (len - 1)), 2666 "-1: got %d/%d (expected FALSE/%d)\n", HIWORD(res), LOWORD(res), len - 1); 2667 ok(!lstrcmpA(bufferA, names[i]), 2668 "-1: got %s (expected %s)\n", bufferA, names[i]); 2669 2670 lstrcpyW(expectedW, bufferW); 2671 res = DoEnvironmentSubstW(bufferW, len - 1); 2672 ok(!HIWORD(res) && (LOWORD(res) == (len - 1)), 2673 "-1: got %d/%d (expected FALSE/%d)\n", HIWORD(res), LOWORD(res), len - 1); 2674 ok(!lstrcmpW(bufferW, expectedW), 2675 "-1: got %s (expected %s)\n", wine_dbgstr_w(bufferW), wine_dbgstr_w(expectedW)); 2676 2677 2678 /* unknown variable */ 2679 /* result: TRUE / string length including terminating 0 / the buffer is untouched */ 2680 memset(bufferA, '#', MAX_PATH - 1); 2681 bufferA[MAX_PATH - 1] = 0; 2682 lstrcpyA(bufferA, does_not_existA); 2683 MultiByteToWideChar(CP_ACP, 0, bufferA, MAX_PATH, bufferW, ARRAY_SIZE(bufferW)); 2684 2685 res2 = lstrlenA(does_not_existA) + 1; 2686 res = DoEnvironmentSubstA(bufferA, MAX_PATH); 2687 ok(HIWORD(res) && (LOWORD(res) == res2), 2688 "%d: got %d/%d (expected TRUE/%d)\n", i, HIWORD(res), LOWORD(res), res2); 2689 ok(!lstrcmpA(bufferA, does_not_existA), 2690 "%d: got %s (expected %s)\n", i, bufferA, does_not_existA); 2691 2692 res = DoEnvironmentSubstW(bufferW, MAX_PATH); 2693 ok(HIWORD(res) && (LOWORD(res) == res2), 2694 "%d: got %d/%d (expected TRUE/%d)\n", i, HIWORD(res), LOWORD(res), res2); 2695 ok(!lstrcmpW(bufferW, does_not_existW), 2696 "%d: got %s (expected %s)\n", i, wine_dbgstr_w(bufferW), wine_dbgstr_w(does_not_existW)); 2697 2698 2699 if (0) 2700 { 2701 /* NULL crashes on windows */ 2702 res = DoEnvironmentSubstA(NULL, MAX_PATH); 2703 res = DoEnvironmentSubstW(NULL, MAX_PATH); 2704 } 2705 } 2706 2707 static void test_PathYetAnotherMakeUniqueName(void) 2708 { 2709 static const WCHAR shortW[] = {'f','i','l','e','.','t','s','t',0}; 2710 static const WCHAR short2W[] = {'f','i','l','e',' ','(','2',')','.','t','s','t',0}; 2711 static const WCHAR tmpW[] = {'t','m','p',0}; 2712 static const WCHAR longW[] = {'n','a','m','e',0}; 2713 static const WCHAR long2W[] = {'n','a','m','e',' ','(','2',')',0}; 2714 WCHAR nameW[MAX_PATH], buffW[MAX_PATH], pathW[MAX_PATH]; 2715 HANDLE file; 2716 BOOL ret; 2717 2718 if (!pPathYetAnotherMakeUniqueName) 2719 { 2720 win_skip("PathYetAnotherMakeUniqueName() is not available.\n"); 2721 return; 2722 } 2723 2724 if (0) 2725 { 2726 /* crashes on Windows */ 2727 ret = pPathYetAnotherMakeUniqueName(NULL, NULL, NULL, NULL); 2728 ok(!ret, "got %d\n", ret); 2729 2730 ret = pPathYetAnotherMakeUniqueName(nameW, NULL, NULL, NULL); 2731 ok(!ret, "got %d\n", ret); 2732 } 2733 2734 GetTempPathW(ARRAY_SIZE(pathW), pathW); 2735 2736 /* Using short name only first */ 2737 nameW[0] = 0; 2738 ret = pPathYetAnotherMakeUniqueName(nameW, pathW, shortW, NULL); 2739 ok(ret, "got %d\n", ret); 2740 lstrcpyW(buffW, pathW); 2741 lstrcatW(buffW, shortW); 2742 ok(!lstrcmpW(nameW, buffW), "got %s, expected %s\n", wine_dbgstr_w(nameW), wine_dbgstr_w(buffW)); 2743 2744 /* now create a file with this name and get next name */ 2745 file = CreateFileW(nameW, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL); 2746 ok(file != NULL, "got %p\n", file); 2747 2748 nameW[0] = 0; 2749 ret = pPathYetAnotherMakeUniqueName(nameW, pathW, shortW, NULL); 2750 ok(ret, "got %d\n", ret); 2751 lstrcpyW(buffW, pathW); 2752 lstrcatW(buffW, short2W); 2753 ok(!lstrcmpW(nameW, buffW), "got %s, expected %s\n", wine_dbgstr_w(nameW), wine_dbgstr_w(buffW)); 2754 2755 CloseHandle(file); 2756 2757 /* Using short and long */ 2758 nameW[0] = 0; 2759 ret = pPathYetAnotherMakeUniqueName(nameW, pathW, tmpW, longW); 2760 ok(ret, "got %d\n", ret); 2761 lstrcpyW(buffW, pathW); 2762 lstrcatW(buffW, longW); 2763 ok(!lstrcmpW(nameW, buffW), "got %s, expected %s\n", wine_dbgstr_w(nameW), wine_dbgstr_w(buffW)); 2764 2765 file = CreateFileW(nameW, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL); 2766 ok(file != NULL, "got %p\n", file); 2767 2768 nameW[0] = 0; 2769 ret = pPathYetAnotherMakeUniqueName(nameW, pathW, tmpW, longW); 2770 ok(ret, "got %d\n", ret); 2771 lstrcpyW(buffW, pathW); 2772 lstrcatW(buffW, long2W); 2773 ok(!lstrcmpW(nameW, buffW), "got %s, expected %s\n", wine_dbgstr_w(nameW), wine_dbgstr_w(buffW)); 2774 2775 CloseHandle(file); 2776 2777 /* Using long only */ 2778 nameW[0] = 0; 2779 ret = pPathYetAnotherMakeUniqueName(nameW, pathW, NULL, longW); 2780 ok(ret, "got %d\n", ret); 2781 lstrcpyW(buffW, pathW); 2782 lstrcatW(buffW, longW); 2783 ok(!lstrcmpW(nameW, buffW), "got %s, expected %s\n", wine_dbgstr_w(nameW), wine_dbgstr_w(buffW)); 2784 } 2785 2786 static void test_SHGetKnownFolderIDList(void) 2787 { 2788 PIDLIST_ABSOLUTE pidl; 2789 HRESULT hr; 2790 2791 if (!pSHGetKnownFolderIDList) 2792 { 2793 win_skip("SHGetKnownFolderIDList is not available.\n"); 2794 return; 2795 } 2796 2797 hr = pSHGetKnownFolderIDList(NULL, 0, NULL, NULL); 2798 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); 2799 2800 if (0) { /* crashes on native */ 2801 pidl = (void*)0xdeadbeef; 2802 hr = pSHGetKnownFolderIDList(NULL, 0, NULL, &pidl); 2803 } 2804 /* not a known folder */ 2805 pidl = (void*)0xdeadbeef; 2806 hr = pSHGetKnownFolderIDList(&IID_IUnknown, 0, NULL, &pidl); 2807 ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "got 0x%08x\n", hr); 2808 ok(pidl == NULL, "got %p\n", pidl); 2809 2810 hr = pSHGetKnownFolderIDList(&FOLDERID_Desktop, 0, NULL, NULL); 2811 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); 2812 2813 pidl = (void*)0xdeadbeef; 2814 hr = pSHGetKnownFolderIDList(&FOLDERID_Desktop, 0, NULL, &pidl); 2815 ok(hr == S_OK, "SHGetKnownFolderIDList failed: 0x%08x\n", hr); 2816 ok(ILIsEmpty(pidl), "pidl should be empty.\n"); 2817 ok(pidl->mkid.cb == 0, "get wrong value: %d\n", pidl->mkid.cb); 2818 ILFree(pidl); 2819 2820 pidl = (void*)0xdeadbeef; 2821 hr = pSHGetKnownFolderIDList(&FOLDERID_Desktop, KF_FLAG_NO_ALIAS, NULL, &pidl); 2822 ok(hr == S_OK, "SHGetKnownFolderIDList failed: 0x%08x\n", hr); 2823 todo_wine ok(!ILIsEmpty(pidl), "pidl should not be empty.\n"); 2824 todo_wine ok(pidl->mkid.cb == 20, "get wrong value: %d\n", pidl->mkid.cb); 2825 ILFree(pidl); 2826 2827 pidl = (void*)0xdeadbeef; 2828 hr = pSHGetKnownFolderIDList(&FOLDERID_Documents, 0, NULL, &pidl); 2829 ok(hr == S_OK, "SHGetKnownFolderIDList failed: 0x%08x\n", hr); 2830 ok(!ILIsEmpty(pidl), "pidl should not be empty.\n"); 2831 ok(pidl->mkid.cb == 20, "get wrong value: %d\n", pidl->mkid.cb); 2832 ILFree(pidl); 2833 2834 pidl = (void*)0xdeadbeef; 2835 hr = pSHGetKnownFolderIDList(&FOLDERID_Documents, KF_FLAG_NO_ALIAS, NULL, &pidl); 2836 ok(hr == S_OK, "SHGetKnownFolderIDList failed: 0x%08x\n", hr); 2837 ok(!ILIsEmpty(pidl), "pidl should not be empty.\n"); 2838 ok(pidl->mkid.cb == 20, "get wrong value: %d\n", pidl->mkid.cb); 2839 ILFree(pidl); 2840 } 2841 2842 START_TEST(shellpath) 2843 { 2844 if (!init()) return; 2845 2846 loadShell32(); 2847 pGetSystemWow64DirectoryA = (void *)GetProcAddress( GetModuleHandleA("kernel32.dll"), 2848 "GetSystemWow64DirectoryA" ); 2849 if (myARGC >= 3) 2850 doChild(myARGV[2]); 2851 else 2852 { 2853 /* Report missing functions once */ 2854 if (!pSHGetFolderLocation) 2855 win_skip("SHGetFolderLocation is not available\n"); 2856 2857 /* first test various combinations of parameters: */ 2858 test_parameters(); 2859 2860 /* check known values: */ 2861 test_PidlTypes(); 2862 test_GUIDs(); 2863 test_EnvVars(); 2864 testWinDir(); 2865 testSystemDir(); 2866 test_NonExistentPath(); 2867 test_SHGetFolderPathEx(); 2868 test_knownFolders(); 2869 test_DoEnvironmentSubst(); 2870 test_PathYetAnotherMakeUniqueName(); 2871 test_SHGetKnownFolderIDList(); 2872 } 2873 } 2874