55#define NONAMELESSUNION
65#define _WIN32_WINNT 0x0600
81#include "wine/unicode.h"
88#define UNIMPLEMENTED_FLAGS \
89(OFN_DONTADDTORECENT |\
90OFN_NODEREFERENCELINKS | OFN_NOREADONLYRETURN |\
114static HHOOK s_hFileDialogHook =
NULL;
115static LONG s_nFileDialogHookCount = 0;
117#define MAX_TRANSLATE 8
118static HWND s_ahwndTranslate[MAX_TRANSLATE] = {
NULL };
120static void FILEDLG95_AddRemoveTranslate(
HWND hwndOld,
HWND hwndNew)
123 for (
i = 0;
i < MAX_TRANSLATE; ++
i)
125 if (s_ahwndTranslate[
i] == hwndOld)
127 s_ahwndTranslate[
i] = hwndNew;
139 if (s_ahwndTranslate[
i] ==
NULL)
143 if (fodInfos ==
NULL)
147 if (hwndView == hwndFocus ||
IsChild(hwndView, hwndFocus))
149 IShellView_TranslateAccelerator(fodInfos->
Shell.FOIShellView, pMsg);
172 for (
i = 0;
i < MAX_TRANSLATE; ++
i)
174 if (FILEDLG95_DoTranslate(
i, hwndFocus, pMsg))
197#define ITEM_NOTFOUND -1
200#define WM_GETISHELLBROWSER WM_USER+7
202#define TBPLACES_CMDID_PLACE0 0xa064
203#define TBPLACES_CMDID_PLACE1 0xa065
204#define TBPLACES_CMDID_PLACE2 0xa066
205#define TBPLACES_CMDID_PLACE3 0xa067
206#define TBPLACES_CMDID_PLACE4 0xa068
214#define CBGetItemDataPtr(hwnd,iItemId) \
215 SendMessageW(hwnd, CB_GETITEMDATA, (WPARAM)(iItemId), 0)
221 {
'S',
'o',
'f',
't',
'w',
'a',
'r',
'e',
'\\',
'M',
'i',
'c',
'r',
'o',
's',
'o',
'f',
't',
'\\',
222 'W',
'i',
'n',
'd',
'o',
'w',
's',
'\\',
'C',
'u',
'r',
'r',
'e',
'n',
't',
'V',
'e',
'r',
's',
'i',
'o',
'n',
'\\',
223 'E',
'x',
'p',
'l',
'o',
'r',
'e',
'r',
'\\',
'C',
'o',
'm',
'D',
'l',
'g',
'3',
'2',
'\\',
224 'L',
'a',
's',
't',
'V',
'i',
's',
'i',
't',
'e',
'd',
'M',
'R',
'U',0};
227static const WCHAR filedlg_info_propnameW[] = {
'F',
'i',
'l',
'e',
'O',
'p',
'e',
'n',
'D',
'l',
'g',
'I',
'n',
'f',
'o',
's',0};
358 static const WCHAR noplacesbarW[] = {
'N',
'o',
'P',
'l',
'a',
'c',
'e',
's',
'B',
'a',
'r',0};
380 static const int default_places[] =
402 static const WCHAR placeW[] = {
'P',
'l',
'a',
'c',
'e',
'%',
'd',0};
413 WARN(
"Unrecognized special folder %u.\n",
value);
455 FIXME(
"Flags 0x%08x not yet implemented\n",
462 templateid = NEWFILEOPENV2ORD;
464 templateid = NEWFILEOPENORD;
671 if (
ret &&
info->ofnInfos->lpstrFile &&
info->ofnInfos->lpstrFileTitle)
716 LPSHELLFOLDER psfDesktop;
722 if (
FAILED(IShellFolder_GetDisplayNameOf(psfDesktop, pidl, SHGDN_FORPARSING, &strret))) {
723 IShellFolder_Release(psfDesktop);
727 IShellFolder_Release(psfDesktop);
754 lstrcatW(lpstrPathAndFile, lpstrFile);
760 lstrcpyW(lpstrPathAndFile+2, lpstrFile);
762 lstrcpyW(lpstrPathAndFile, lpstrFile);
767 lstrcpyW(lpstrPathAndFile, lpstrTemp);
778 UINT nStrCharCount = 0;
788 while ( nStrCharCount <= nStrLen )
790 if ( lpstrEdit[nStrCharCount]==
'"' )
793 while ((nStrCharCount <= nStrLen) && (lpstrEdit[nStrCharCount]!=
'"'))
795 (*lpstrFileList)[nFileIndex++] = lpstrEdit[nStrCharCount];
798 (*lpstrFileList)[nFileIndex++] = 0;
805 if ((nStrLen > 0) && (nFileIndex == 0) )
807 lstrcpyW(*lpstrFileList, lpstrEdit);
808 nFileIndex =
lstrlenW(lpstrEdit) + 1;
813 (*lpstrFileList)[nFileIndex++] =
'\0';
815 *sizeUsed = nFileIndex;
826 HWND hwndChild, hwndStc32;
827 RECT rectParent, rectChild, rectStc32;
836 RECT rectHelp, rectCancel;
861 rectParent.
bottom -= help_fixup;
884 if (hwndChild != hwndStc32)
890 if (hwndStc32 && rectChild.left > rectStc32.
right)
893 rectChild.left += rectParent.
right;
894 rectChild.left -= rectStc32.
right;
897 if (rectChild.top >= rectStc32.
bottom)
900 rectChild.top += rectParent.
bottom;
901 rectChild.top -= rectStc32.
bottom - rectStc32.
top;
904 SetWindowPos(hwndChild, 0, rectChild.left, rectChild.top,
914 if (hwndChild != hwndChildDlg)
922 rectChild.left += rectStc32.
left;
923 rectChild.top += rectStc32.
top;
925 SetWindowPos(hwndChild, 0, rectChild.left, rectChild.top,
948 chgy = rectChild.
bottom - ( rectStc32.
bottom - rectStc32.
top) - help_fixup;
958 chgy = rectChild.
bottom - help_fixup;
964 rectParent.
right - rectParent.
left + chgx,
965 rectParent.
bottom - rectParent.
top + chgy,
1048 temp.tmplate.dwExtendedStyle = 0;
1049 temp.tmplate.cdit = 0;
1052 temp.tmplate.cx = 0;
1053 temp.tmplate.cy = 0;
1076 TRACE(
"%p %d\n", hwndParentDlg, uCode);
1078 if (!fodInfos || !fodInfos->
DlgInfos.hwndCustomDlg)
1081 TRACE(
"CALL NOTIFY for %d\n", uCode);
1094 TRACE(
"RET NOTIFY retval %#lx\n", hook_result);
1105 TRACE(
"CDM_GETFILEPATH:\n");
1147 if(!fodInfos)
return FALSE;
1156 TRACE(
"CDM_GETFOLDERPATH:\n");
1176 TRACE(
"CDM_GETSPEC:\n");
1188 TRACE(
"CDM_SETCONTROLTEXT:\n");
1207 else retval =
FALSE;
1212 FIXME(
"message CDM_FIRST+%04x not implemented\n", uMsg -
CDM_FIRST);
1289 else if( rc.top > rcview.
bottom)
1300 rc.right - rc.left + chgx, rc.bottom - rc.top,
1317 else if( rc.left > rcview.
right)
1333 rc.right - rc.left + chgx, rc.bottom - rc.top,
1347 rc.right - rc.left + chgx,
1348 rc.bottom - rc.top + chgy,
1358 if(fodInfos->
DlgInfos.hwndCustomDlg &&
1366 if( rc.top > rcview.
bottom)
1371 rc.right - rc.left, rc.bottom - rc.top,
1374 else if( rc.left > rcview.
right)
1379 rc.right - rc.left, rc.bottom - rc.top,
1435 style &= ~WS_SIZEBOX;
1464 if( fodInfos->
DlgInfos.hwndCustomDlg)
1480 rcstc.left, rcstc.top, rcstc.right - rcstc.left, rcstc.bottom - rcstc.top,
1508 if (++s_nFileDialogHookCount == 1)
1513 FILEDLG95_AddRemoveTranslate(
NULL,
hwnd);
1556 FILEDLG95_AddRemoveTranslate(
hwnd,
NULL);
1557 if (--s_nFileDialogHookCount == 0)
1560 s_hFileDialogHook =
NULL;
1635 static const WCHAR szwSlash[] = {
'\\', 0 };
1636 static const WCHAR szwStar[] = {
'*',0 };
1661 TRACE(
"%p\n", fodInfos);
1670 if (win2000plus) win98plus =
TRUE;
1672 TRACE(
"Running on 2000+ %d, 98+ %d\n", win2000plus, win98plus);
1701 rectTB.
top = rectlook.
top-1;
1790 handledPath =
FALSE;
1819 TRACE(
"Value in Filename includes path, overriding InitialDir: %s, %s\n",
1861 TRACE(
"Value in InitDir is not an existing path, changed to (nil)\n");
1888 if (!win2000plus && fodInfos->
filename &&
1910 TRACE(
"Value in Filename includes path, overriding initdir: %s, %s\n",
1917 if (!handledPath && win2000plus) {
1933 if (win98plus && !handledPath && fodInfos->
filter && *fodInfos->
filter) {
1944 if(! *lpstrPos)
break;
1945 lpstrPos +=
lstrlenW(lpstrPos) + 1;
1948 if(! *lpstrPos)
break;
1954 lpstrPos +=
lstrlenW(lpstrPos) + 1;
1963 TRACE(
"No initial dir specified, but files of type %s found in current, so using it\n",
1972 if (!handledPath && (win2000plus || win98plus)) {
1990 }
else if (!handledPath) {
2052 if (fodInfos->
DlgInfos.hwndCustomDlg)
2083 RECT rectDlg, rectHelp, rectCancel;
2109 TRACE(
"dir=%s file=%s\n",
2129 IShellBrowser_BrowseObject(fodInfos->
Shell.FOIShellBrowser,pidlItemId, SBSP_ABSOLUTE);
2153 TRACE(
"%p, %p\n",
info->ShellInfos.hwndOwner, pidl);
2155 IShellBrowser_BrowseObject(
info->Shell.FOIShellBrowser, pidl, SBSP_ABSOLUTE);
2234 fodInfos->
DlgInfos.dwDlgProp &= ~FODPROP_USEVIEW;
2277 TRACE(
"canceled\n");
2286 TRACE(
"canceled\n");
2305 UINT nCount, nSizePath;
2326 LPWSTR lpstrTemp = lpstrFileList;
2328 for ( nCount = 0; nCount < nFileCount; nCount++ )
2335 WCHAR lpstrNotFound[100];
2336 WCHAR lpstrMsg[100];
2338 static const WCHAR nl[] = {
'\n',0};
2354 lpstrTemp +=
lstrlenW(lpstrTemp) + 1;
2359 nSizePath =
lstrlenW(lpstrPathSpec) + 1;
2365 FIXME(
"Components have to be separated by blanks\n");
2416 WCHAR mru_list[32], *cur_mru_slot;
2417 BOOL taken[25] = {0};
2418 DWORD mru_list_size =
sizeof(mru_list), key_type = -1,
i;
2419 HKEY hkey_tmp, *hkey;
2428 *stored_path =
'\0';
2432 WARN(
"Unable to create MRU key: %d\n",
ret);
2437 (
LPBYTE)mru_list, &mru_list_size);
2442 WARN(
"Error getting MRUList data: type: %d, ret: %d\n", key_type,
ret);
2447 for(cur_mru_slot = mru_list; *cur_mru_slot; ++cur_mru_slot){
2449 DWORD value_data_size =
sizeof(value_data);
2451 *value_name = *cur_mru_slot;
2454 &key_type, (
LPBYTE)value_data, &value_data_size);
2456 WARN(
"Error getting MRU slot data: type: %d, ret: %d\n", key_type,
ret);
2473 for(cur_mru_slot = mru_list; *cur_mru_slot; ++cur_mru_slot)
2474 taken[*cur_mru_slot -
'a'] =
TRUE;
2475 for(
i = 0;
i < 25; ++
i){
2482 return *cur_mru_slot;
2510 WCHAR *path_ends, *
final;
2524 final[final_len-1] =
'\0';
2527 final_len *
sizeof(
WCHAR));
2539 WCHAR old_mru_list[32], new_mru_list[32];
2540 WCHAR *old_mru_slot, *new_mru_slot = new_mru_list;
2541 DWORD mru_list_size =
sizeof(old_mru_list), key_type;
2544 (
LPBYTE)old_mru_list, &mru_list_size);
2547 new_mru_list[0] =
slot;
2548 new_mru_list[1] =
'\0';
2550 WARN(
"Error getting MRUList data: type: %d, ret: %d\n", key_type,
ret);
2557 *new_mru_slot++ =
slot;
2558 for(old_mru_slot = old_mru_list; *old_mru_slot; ++old_mru_slot){
2559 if(*old_mru_slot !=
slot)
2560 *new_mru_slot++ = *old_mru_slot;
2562 *new_mru_slot =
'\0';
2568 WARN(
"Error saving MRUList data: %d\n",
ret);
2597static const WCHAR s_subkey[] =
2599 'S',
'o',
'f',
't',
'w',
'a',
'r',
'e',
'\\',
'M',
'i',
'c',
'r',
'o',
's',
'o',
'f',
't',
'\\',
2600 'W',
'i',
'n',
'd',
'o',
'w',
's',
'\\',
'C',
'u',
'r',
'r',
'e',
'n',
't',
'V',
'e',
'r',
's',
2601 'i',
'o',
'n',
'\\',
'E',
'x',
'p',
'l',
'o',
'r',
'e',
'r',
'\\',
'C',
'o',
'm',
'D',
'l',
'g',
2602 '3',
'2',
'\\',
'O',
'p',
'e',
'n',
'S',
'a',
'v',
'e',
'M',
'R',
'U',0
2604static const WCHAR s_szAst[] = {
'*', 0 };
2625#define MRU_STRING 0x0000
2626#define MRU_BINARY 0x0001
2627#define MRU_CACHEWRITE 0x0002
2633static CREATEMRULISTW s_pCreateMRUListW =
NULL;
2637static ADDMRUSTRINGW s_pAddMRUStringW =
NULL;
2641static FINDMRUSTRINGW s_pFindMRUStringW =
NULL;
2645static ENUMMRULISTW s_pEnumMRUListW =
NULL;
2649static FREEMRULIST s_pFreeMRUList =
NULL;
2651static BOOL FILEDLG_InitMRUList(
void)
2665 if (!s_pCreateMRUListW ||
2666 !s_pAddMRUStringW ||
2667 !s_pFindMRUStringW ||
2680 static const WCHAR s_image_exts[][6] =
2685 {
'j',
'p',
'e',
'g',0 },
2687 {
'j',
'f',
'i',
'f',0 },
2691 {
't',
'i',
'f',
'f',0 }
2716 if (!defext || !*defext || !FILEDLG_InitMRUList())
2725 if (!
result && hOpenSaveMRT)
2731 mi.hKey = hOpenSaveMRT;
2732 mi.lpszSubKey = defext;
2734 hList = (*s_pCreateMRUListW)(&
mi);
2737 ret = (*s_pEnumMRUListW)(
hList, 0, szText,
sizeof(szText));
2743 (*s_pFreeMRUList)(
hList);
2749 if (stored_path[0] == 0)
2752 if (ExtIsPicture(defext))
2773 if (!defext || !*defext || !FILEDLG_InitMRUList())
2782 if (!
result && hOpenSaveMRT)
2788 mi.hKey = hOpenSaveMRT;
2789 mi.lpszSubKey = defext;
2791 hList = (*s_pCreateMRUListW)(&
mi);
2795 (*s_pFreeMRUList)(
hList);
2801 mi.hKey = hOpenSaveMRT;
2802 mi.lpszSubKey = s_szAst;
2804 hList = (*s_pCreateMRUListW)(&
mi);
2808 (*s_pFreeMRUList)(
hList);
2824 strMsgTitle[0] =
'\0';
2832 int nOpenAction = defAction;
2833 LPWSTR lpszTemp, lpszTemp1;
2835 static const WCHAR szwInvalid[] = {
'/',
':',
'<',
'>',
'|', 0};
2846 lpszTemp1 = lpszTemp = lpstrPathAndFile;
2849 LPSHELLFOLDER lpsfChild;
2860 lpszTemp = lpszTemp +
lstrlenW(lpwstrTemp);
2865 static const WCHAR wszWild[] = {
'*',
'?', 0 };
2873 lpszTemp1 = lpszTemp;
2878 if(
lstrlenW(lpwstrTemp)==2 && lpwstrTemp[1] ==
':' &&
2879 ((lpwstrTemp[0] >=
'a' && lpwstrTemp[0] <=
'z') ||
2880 (lpwstrTemp[0] >=
'A' && lpwstrTemp[0] <=
'Z')))
2890 if((
dwAttributes & (SFGAO_FOLDER | SFGAO_FILESYSANCESTOR)) == (SFGAO_FOLDER | SFGAO_FILESYSANCESTOR))
2892 if(
FAILED(IShellFolder_BindToObject(*ppsf, pidl, 0, &IID_IShellFolder, (
LPVOID*)&lpsfChild)))
2894 ERR(
"bind to failed\n");
2897 IShellFolder_Release(*ppsf);
2915 (lpwstrTemp[
lstrlenW(lpwstrTemp)-1] ==
'\\'))
2957 UINT nFileCount = 0;
2961 LPSHELLFOLDER lpsf =
NULL;
2982 TRACE(
"count=%u len=%u file=%s\n", nFileCount, sizeUsed,
debugstr_w(lpstrFileList));
3029 TRACE(
"end validate sf=%p\n", lpsf);
3052 TRACE(
"ONOPEN_BROWSE\n");
3055 if(
SUCCEEDED(IShellFolder_QueryInterface( lpsf, &IID_IPersistFolder2, (
LPVOID*)&ppf2)))
3058 IPersistFolder2_GetCurFolder(ppf2, &pidlCurrent);
3059 IPersistFolder2_Release(ppf2);
3062 if (
SUCCEEDED(IShellBrowser_BrowseObject(fodInfos->
Shell.FOIShellBrowser, pidlCurrent, SBSP_ABSOLUTE))
3071 if (fodInfos->
Shell.FOIShellView)
3072 IShellView_Refresh(fodInfos->
Shell.FOIShellView);
3105 static const WCHAR szwDot[] = {
'.',0};
3117 strcpyW(filterExt, lpstrFilter);
3125 if (filterSearchIndex)
3127 filterSearchIndex[0] = 0;
3128 pchNext = filterSearchIndex + 1;
3135 while (*
pch ==
'*' || *
pch ==
'.' || *
pch ==
'?')
3151 if (!the_ext && pchFirst && *pchFirst)
3162 the_ext = fodInfos->
defext;
3165 if (the_ext && *the_ext &&
lstrcmpiW(&
ext[1], the_ext) != 0)
3171 lstrcatW(lpstrPathAndFile, szwDot);
3173 lstrcatW(lpstrPathAndFile, the_ext);
3204 static const WCHAR szwDot[] = {
'.',0};
3213 WCHAR* filterSearchIndex;
3220 filterSearchIndex =
wcschr(filterExt,
';');
3221 if (filterSearchIndex)
3223 filterSearchIndex[0] =
'\0';
3229 filterSearchIndex =
wcschr(filterExt,
'.');
3230 if (filterSearchIndex++ && !
wcschr(filterSearchIndex,
'*') && !
wcschr(filterSearchIndex,
'?'))
3232 lstrcpyW(filterExt, filterSearchIndex);
3251 lstrcatW(lpstrPathAndFile, szwDot);
3253 lstrcatW(lpstrPathAndFile, filterExt);
3277 WCHAR lpstrOverwrite[100];
3295 WCHAR lpstrCreate[100];
3355 tempFileA,
sizeof(tempFileA),
NULL,
NULL);
3387 FILEDLG95_MRU_save_ext(lpstrPathAndFile);
3413 if(lpsf) IShellFolder_Release(lpsf);
3464 if(
SUCCEEDED(IShellView_GetItemObject(fodInfos->
Shell.FOIShellView,
3469 CMINVOKECOMMANDINFO ci;
3470 ZeroMemory(&ci,
sizeof(CMINVOKECOMMANDINFO));
3471 ci.cbSize =
sizeof(CMINVOKECOMMANDINFO);
3475 IContextMenu_InvokeCommand(pcm, &ci);
3476 IContextMenu_Release(pcm);
3494 if(
SUCCEEDED(IShellBrowser_BrowseObject(fodInfos->
Shell.FOIShellBrowser,
3518 if (fodInfos->
Shell.FOIShellView)
3520 IShellView_DestroyViewWindow(fodInfos->
Shell.FOIShellView);
3521 IShellView_Release(fodInfos->
Shell.FOIShellView);
3523 if (fodInfos->
Shell.FOIShellFolder)
3524 IShellFolder_Release(fodInfos->
Shell.FOIShellFolder);
3525 IShellBrowser_Release(fodInfos->
Shell.FOIShellBrowser);
3526 if (fodInfos->
Shell.FOIDataObject)
3527 IDataObject_Release(fodInfos->
Shell.FOIDataObject);
3555 if (! *lpstrPos)
return E_FAIL;
3579 if(! *lpstrPos)
break;
3580 lpstrDisplay = lpstrPos;
3581 lpstrPos +=
lstrlenW(lpstrPos) + 1;
3590 lpstrPos +=
lstrlenW(lpstrPos) + 1;
3596 if (!*lpstrExt)
break;
3685 if (fodInfos->
Shell.FOIShellView)
3686 IShellView_Refresh(fodInfos->
Shell.FOIShellView);
3706 for(
i=0;
i<iCount;
i++)
3733 for(iPos = iCount-1;iPos>=0;iPos--)
3754 static const WCHAR wszRootedAtDesktop[] = {
'S',
'o',
'f',
't',
'w',
'a',
'r',
'e',
'\\',
3755 'M',
'i',
'c',
'r',
'o',
's',
'o',
'f',
't',
'\\',
'W',
'i',
'n',
'd',
'o',
'w',
's',
'\\',
3756 'C',
'u',
'r',
'r',
'e',
'n',
't',
'V',
'e',
'r',
's',
'i',
'o',
'n',
'\\',
3757 'E',
'x',
'p',
'l',
'o',
'r',
'e',
'r',
'\\',
'D',
'e',
's',
'k',
't',
'o',
'p',
'\\',
3758 'N',
'a',
'm',
'e',
'S',
'p',
'a',
'c',
'e',
'\\',
'{',
'9',
'D',
'2',
'0',
'A',
'A',
'E',
'8',
3759 '-',
'0',
'6',
'2',
'5',
'-',
'4',
'4',
'B',
'0',
'-',
'9',
'C',
'A',
'7',
'-',
3760 '7',
'1',
'8',
'8',
'9',
'C',
'2',
'2',
'5',
'4',
'D',
'9',
'}',0 };
3773 LPITEMIDLIST pidlDrives, pidlTmp, pidlTmp1, pidlAbsTmp;
3776 LookInInfos *liInfos = heap_alloc_zero(
sizeof(*liInfos));
3778 TRACE(
"%p\n", hwndCombo);
3808 if(
SUCCEEDED(IShellFolder_EnumObjects(psfRoot, hwndCombo, SHCONTF_FOLDERS, &lpeRoot)))
3810 while (
S_OK == IEnumIDList_Next(lpeRoot, 1, &pidlTmp,
NULL))
3820 if(
SUCCEEDED(IShellFolder_BindToObject(psfRoot, pidlTmp,
NULL, &IID_IShellFolder, (
LPVOID*)&psfDrives)))
3823 if(
SUCCEEDED(IShellFolder_EnumObjects(psfDrives, hwndCombo,SHCONTF_FOLDERS, &lpeDrives)))
3825 while (
S_OK == IEnumIDList_Next(lpeDrives, 1, &pidlTmp1,
NULL))
3827 pidlAbsTmp =
ILCombine(pidlTmp, pidlTmp1);
3832 IEnumIDList_Release(lpeDrives);
3834 IShellFolder_Release(psfDrives);
3841 IEnumIDList_Release(lpeRoot);
3843 IShellFolder_Release(psfRoot);
3867 UINT icon_width, icon_height;
3871 if(pDIStruct->
itemID == -1)
3889 0, &sfi,
sizeof (sfi), shgfi_flags );
3906 if(pDIStruct->
itemState & ODS_COMBOBOXEDIT)
3914 rectIcon.
left = pDIStruct->
rcItem.
left + 1 + icon_width/2 * iIndentation;
3951 TRACE(
"%p\n", fodInfos);
3969 if(
SUCCEEDED(IShellBrowser_BrowseObject(fodInfos->
Shell.FOIShellBrowser,
3997 TRACE(
"%p, %p, %d\n",
hwnd, pidl, iInsertId);
4005 tmpFolder = heap_alloc_zero(
sizeof(*tmpFolder));
4010 while ((pidlNext =
ILGetNext(pidlNext)))
4020 sfi.
dwAttributes = SFGAO_FILESYSANCESTOR | SFGAO_FILESYSTEM;
4069 if (pidl == pidlParent)