1 // Windows/Shell.cpp 2 3 #include "StdAfx.h" 4 5 #include "../Common/MyCom.h" 6 #ifndef _UNICODE 7 #include "../Common/StringConvert.h" 8 #endif 9 10 #include "COM.h" 11 #include "Shell.h" 12 13 #ifndef _UNICODE 14 extern bool g_IsNT; 15 #endif 16 17 namespace NWindows { 18 namespace NShell { 19 20 #ifndef UNDER_CE 21 22 // SHGetMalloc is unsupported in Windows Mobile? 23 24 void CItemIDList::Free() 25 { 26 if (m_Object == NULL) 27 return; 28 CMyComPtr<IMalloc> shellMalloc; 29 if (::SHGetMalloc(&shellMalloc) != NOERROR) 30 throw 41099; 31 shellMalloc->Free(m_Object); 32 m_Object = NULL; 33 } 34 35 /* 36 CItemIDList::(LPCITEMIDLIST itemIDList): m_Object(NULL) 37 { *this = itemIDList; } 38 CItemIDList::(const CItemIDList& itemIDList): m_Object(NULL) 39 { *this = itemIDList; } 40 41 CItemIDList& CItemIDList::operator=(LPCITEMIDLIST object) 42 { 43 Free(); 44 if (object != 0) 45 { 46 UINT32 size = GetSize(object); 47 m_Object = (LPITEMIDLIST)CoTaskMemAlloc(size); 48 if (m_Object != NULL) 49 MoveMemory(m_Object, object, size); 50 } 51 return *this; 52 } 53 54 CItemIDList& CItemIDList::operator=(const CItemIDList &object) 55 { 56 Free(); 57 if (object.m_Object != NULL) 58 { 59 UINT32 size = GetSize(object.m_Object); 60 m_Object = (LPITEMIDLIST)CoTaskMemAlloc(size); 61 if (m_Object != NULL) 62 MoveMemory(m_Object, object.m_Object, size); 63 } 64 return *this; 65 } 66 */ 67 68 ///////////////////////////// 69 // CDrop 70 71 void CDrop::Attach(HDROP object) 72 { 73 Free(); 74 m_Object = object; 75 m_Assigned = true; 76 } 77 78 void CDrop::Free() 79 { 80 if (m_MustBeFinished && m_Assigned) 81 Finish(); 82 m_Assigned = false; 83 } 84 85 UINT CDrop::QueryCountOfFiles() 86 { 87 return QueryFile(0xFFFFFFFF, (LPTSTR)NULL, 0); 88 } 89 90 UString CDrop::QueryFileName(UINT fileIndex) 91 { 92 UString fileName; 93 #ifndef _UNICODE 94 if (!g_IsNT) 95 { 96 AString fileNameA; 97 UINT bufferSize = QueryFile(fileIndex, (LPTSTR)NULL, 0); 98 QueryFile(fileIndex, fileNameA.GetBuffer(bufferSize + 2), bufferSize + 1); 99 fileNameA.ReleaseBuffer(); 100 fileName = GetUnicodeString(fileNameA); 101 } 102 else 103 #endif 104 { 105 UINT bufferSize = QueryFile(fileIndex, (LPWSTR)NULL, 0); 106 QueryFile(fileIndex, fileName.GetBuffer(bufferSize + 2), bufferSize + 1); 107 fileName.ReleaseBuffer(); 108 } 109 return fileName; 110 } 111 112 void CDrop::QueryFileNames(UStringVector &fileNames) 113 { 114 UINT numFiles = QueryCountOfFiles(); 115 fileNames.ClearAndReserve(numFiles); 116 for (UINT i = 0; i < numFiles; i++) 117 fileNames.AddInReserved(QueryFileName(i)); 118 } 119 120 121 bool GetPathFromIDList(LPCITEMIDLIST itemIDList, CSysString &path) 122 { 123 bool result = BOOLToBool(::SHGetPathFromIDList(itemIDList, path.GetBuffer(MAX_PATH * 2))); 124 path.ReleaseBuffer(); 125 return result; 126 } 127 128 #endif 129 130 #ifdef UNDER_CE 131 132 bool BrowseForFolder(LPBROWSEINFO, CSysString) 133 { 134 return false; 135 } 136 137 bool BrowseForFolder(HWND, LPCTSTR, UINT, LPCTSTR, CSysString &) 138 { 139 return false; 140 } 141 142 bool BrowseForFolder(HWND /* owner */, LPCTSTR /* title */, 143 LPCTSTR /* initialFolder */, CSysString & /* resultPath */) 144 { 145 /* 146 // SHBrowseForFolder doesn't work before CE 6.0 ? 147 if (GetProcAddress(LoadLibrary(L"ceshell.dll", L"SHBrowseForFolder") == 0) 148 MessageBoxW(0, L"no", L"", 0); 149 else 150 MessageBoxW(0, L"yes", L"", 0); 151 */ 152 /* 153 UString s = L"all files"; 154 s += L" (*.*)"; 155 return MyGetOpenFileName(owner, title, initialFolder, s, resultPath, true); 156 */ 157 return false; 158 } 159 160 #else 161 162 bool BrowseForFolder(LPBROWSEINFO browseInfo, CSysString &resultPath) 163 { 164 NWindows::NCOM::CComInitializer comInitializer; 165 LPITEMIDLIST itemIDList = ::SHBrowseForFolder(browseInfo); 166 if (itemIDList == NULL) 167 return false; 168 CItemIDList itemIDListHolder; 169 itemIDListHolder.Attach(itemIDList); 170 return GetPathFromIDList(itemIDList, resultPath); 171 } 172 173 174 int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data) 175 { 176 #ifndef UNDER_CE 177 switch(uMsg) 178 { 179 case BFFM_INITIALIZED: 180 { 181 SendMessage(hwnd, BFFM_SETSELECTION, TRUE, data); 182 break; 183 } 184 /* 185 case BFFM_SELCHANGED: 186 { 187 TCHAR dir[MAX_PATH]; 188 if (::SHGetPathFromIDList((LPITEMIDLIST) lp , dir)) 189 SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)dir); 190 else 191 SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)TEXT("")); 192 break; 193 } 194 */ 195 default: 196 break; 197 } 198 #endif 199 return 0; 200 } 201 202 203 bool BrowseForFolder(HWND owner, LPCTSTR title, UINT ulFlags, 204 LPCTSTR initialFolder, CSysString &resultPath) 205 { 206 CSysString displayName; 207 BROWSEINFO browseInfo; 208 browseInfo.hwndOwner = owner; 209 browseInfo.pidlRoot = NULL; 210 211 // there are Unicode/astring problems in WinCE SDK!!! 212 #ifdef UNDER_CE 213 browseInfo.pszDisplayName = (LPSTR)displayName.GetBuffer(MAX_PATH); 214 browseInfo.lpszTitle = (LPCSTR)title; 215 #else 216 browseInfo.pszDisplayName = displayName.GetBuffer(MAX_PATH); 217 browseInfo.lpszTitle = title; 218 #endif 219 browseInfo.ulFlags = ulFlags; 220 browseInfo.lpfn = (initialFolder != NULL) ? BrowseCallbackProc : NULL; 221 browseInfo.lParam = (LPARAM)initialFolder; 222 return BrowseForFolder(&browseInfo, resultPath); 223 } 224 225 bool BrowseForFolder(HWND owner, LPCTSTR title, 226 LPCTSTR initialFolder, CSysString &resultPath) 227 { 228 return BrowseForFolder(owner, title, 229 #ifndef UNDER_CE 230 BIF_NEWDIALOGSTYLE | 231 #endif 232 BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT, initialFolder, resultPath); 233 // BIF_STATUSTEXT; BIF_USENEWUI (Version 5.0) 234 } 235 236 #ifndef _UNICODE 237 238 typedef BOOL (WINAPI * SHGetPathFromIDListWP)(LPCITEMIDLIST pidl, LPWSTR pszPath); 239 240 bool GetPathFromIDList(LPCITEMIDLIST itemIDList, UString &path) 241 { 242 path.Empty(); 243 SHGetPathFromIDListWP shGetPathFromIDListW = (SHGetPathFromIDListWP) 244 ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHGetPathFromIDListW"); 245 if (shGetPathFromIDListW == 0) 246 return false; 247 bool result = BOOLToBool(shGetPathFromIDListW(itemIDList, path.GetBuffer(MAX_PATH * 2))); 248 path.ReleaseBuffer(); 249 return result; 250 } 251 252 typedef LPITEMIDLIST (WINAPI * SHBrowseForFolderWP)(LPBROWSEINFOW lpbi); 253 254 bool BrowseForFolder(LPBROWSEINFOW browseInfo, UString &resultPath) 255 { 256 NWindows::NCOM::CComInitializer comInitializer; 257 SHBrowseForFolderWP shBrowseForFolderW = (SHBrowseForFolderWP) 258 ::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHBrowseForFolderW"); 259 if (shBrowseForFolderW == 0) 260 return false; 261 LPITEMIDLIST itemIDList = shBrowseForFolderW(browseInfo); 262 if (itemIDList == NULL) 263 return false; 264 CItemIDList itemIDListHolder; 265 itemIDListHolder.Attach(itemIDList); 266 return GetPathFromIDList(itemIDList, resultPath); 267 } 268 269 270 int CALLBACK BrowseCallbackProc2(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data) 271 { 272 switch(uMsg) 273 { 274 case BFFM_INITIALIZED: 275 { 276 SendMessageW(hwnd, BFFM_SETSELECTIONW, TRUE, data); 277 break; 278 } 279 /* 280 case BFFM_SELCHANGED: 281 { 282 wchar_t dir[MAX_PATH * 2]; 283 284 if (shGetPathFromIDListW((LPITEMIDLIST)lp , dir)) 285 SendMessageW(hwnd, BFFM_SETSTATUSTEXTW, 0, (LPARAM)dir); 286 else 287 SendMessageW(hwnd, BFFM_SETSTATUSTEXTW, 0, (LPARAM)L""); 288 break; 289 } 290 */ 291 default: 292 break; 293 } 294 return 0; 295 } 296 297 298 static bool BrowseForFolder(HWND owner, LPCWSTR title, UINT ulFlags, 299 LPCWSTR initialFolder, UString &resultPath) 300 { 301 UString displayName; 302 BROWSEINFOW browseInfo; 303 browseInfo.hwndOwner = owner; 304 browseInfo.pidlRoot = NULL; 305 browseInfo.pszDisplayName = displayName.GetBuffer(MAX_PATH); 306 browseInfo.lpszTitle = title; 307 browseInfo.ulFlags = ulFlags; 308 browseInfo.lpfn = (initialFolder != NULL) ? BrowseCallbackProc2 : NULL; 309 browseInfo.lParam = (LPARAM)initialFolder; 310 return BrowseForFolder(&browseInfo, resultPath); 311 } 312 313 bool BrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR initialFolder, UString &resultPath) 314 { 315 if (g_IsNT) 316 return BrowseForFolder(owner, title, 317 BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS 318 // | BIF_STATUSTEXT // This flag is not supported when BIF_NEWDIALOGSTYLE is specified. 319 , initialFolder, resultPath); 320 // BIF_STATUSTEXT; BIF_USENEWUI (Version 5.0) 321 CSysString s; 322 bool res = BrowseForFolder(owner, GetSystemString(title), 323 BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS 324 // | BIF_STATUSTEXT // This flag is not supported when BIF_NEWDIALOGSTYLE is specified. 325 , GetSystemString(initialFolder), s); 326 resultPath = GetUnicodeString(s); 327 return res; 328 } 329 330 #endif 331 332 #endif 333 334 }} 335