Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenfiledefext.cpp
Go to the documentation of this file.
00001 /* 00002 * Provides default file shell extension 00003 * 00004 * Copyright 2005 Johannes Anderwald 00005 * Copyright 2012 Rafal Harabien 00006 * 00007 * This library is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * This library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with this library; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00020 */ 00021 00022 #include <precomp.h> 00023 00024 WINE_DEFAULT_DEBUG_CHANNEL(shell); 00025 00026 BOOL PathIsExeW(LPCWSTR lpszPath); 00027 00028 BOOL CFileVersionInfo::Load(LPCWSTR pwszPath) 00029 { 00030 ULONG cbInfo = GetFileVersionInfoSizeW(pwszPath, NULL); 00031 if (!cbInfo) 00032 { 00033 WARN("GetFileVersionInfoSize %ls failed\n", pwszPath); 00034 return FALSE; 00035 } 00036 00037 m_pInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbInfo); 00038 if (!m_pInfo) 00039 { 00040 ERR("HeapAlloc failed bytes %x\n", cbInfo); 00041 return FALSE; 00042 } 00043 00044 if (!GetFileVersionInfoW(pwszPath, 0, cbInfo, m_pInfo)) 00045 { 00046 ERR("GetFileVersionInfoW failed\n"); 00047 return FALSE; 00048 } 00049 00050 LPLANGANDCODEPAGE lpLangCode; 00051 UINT cBytes; 00052 if (!VerQueryValueW(m_pInfo, L"\\VarFileInfo\\Translation", (LPVOID *)&lpLangCode, &cBytes) || cBytes < sizeof(LANGANDCODEPAGE)) 00053 { 00054 ERR("VerQueryValueW failed\n"); 00055 return FALSE; 00056 } 00057 00058 /* FIXME: find language from current locale / if not available, 00059 * default to english 00060 * for now default to first available language 00061 */ 00062 m_wLang = lpLangCode->wLang; 00063 m_wCode = lpLangCode->wCode; 00064 TRACE("Lang %hx Code %hu\n", m_wLang, m_wCode); 00065 00066 return TRUE; 00067 } 00068 00069 LPCWSTR CFileVersionInfo::GetString(LPCWSTR pwszName) 00070 { 00071 if (!m_pInfo) 00072 return NULL; 00073 00074 WCHAR wszBuf[256]; 00075 swprintf(wszBuf, L"\\StringFileInfo\\%04x%04x\\%s", m_wLang, m_wCode, pwszName); 00076 00077 /* Query string in version block */ 00078 LPCWSTR pwszResult = NULL; 00079 UINT cBytes = 0; 00080 if (!VerQueryValueW(m_pInfo, wszBuf, (LPVOID *)&pwszResult, &cBytes)) 00081 pwszResult = NULL; 00082 00083 if (!m_wLang && !m_wCode) 00084 { 00085 /* Try US English */ 00086 swprintf(wszBuf, L"\\StringFileInfo\\%04x%04x\\%s", MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), 1252, pwszName); 00087 if (!VerQueryValueW(m_pInfo, wszBuf, (LPVOID *)&pwszResult, &cBytes)) 00088 pwszResult = NULL; 00089 } 00090 00091 if (!pwszResult) 00092 ERR("VerQueryValueW %ls failed\n", pwszName); 00093 else 00094 TRACE("%ls: %ls\n", pwszName, pwszResult); 00095 00096 return pwszResult; 00097 } 00098 00099 VS_FIXEDFILEINFO *CFileVersionInfo::GetFixedInfo() 00100 { 00101 if (!m_pInfo) 00102 return NULL; 00103 00104 VS_FIXEDFILEINFO *pInfo; 00105 UINT cBytes; 00106 if (!VerQueryValueW(m_pInfo, L"\\", (PVOID*)&pInfo, &cBytes)) 00107 return NULL; 00108 return pInfo; 00109 } 00110 00111 LPCWSTR CFileVersionInfo::GetLangName() 00112 { 00113 if (!m_pInfo) 00114 return NULL; 00115 00116 if (!m_wszLang[0]) 00117 { 00118 if (!VerLanguageNameW(m_wLang, m_wszLang, _countof(m_wszLang))) 00119 ERR("VerLanguageNameW failed\n"); 00120 } 00121 00122 return m_wszLang; 00123 } 00124 00125 UINT 00126 SH_FormatInteger(LONGLONG Num, LPWSTR pwszResult, UINT cchResultMax) 00127 { 00128 // Print the number in uniform mode 00129 WCHAR wszNumber[24]; 00130 swprintf(wszNumber, L"%I64u", Num); 00131 00132 // Get system strings for decimal and thousand separators. 00133 WCHAR wszDecimalSep[8], wszThousandSep[8]; 00134 GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, wszDecimalSep, _countof(wszDecimalSep)); 00135 GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, wszThousandSep, _countof(wszThousandSep)); 00136 00137 // Initialize format for printing the number in bytes 00138 NUMBERFMTW nf; 00139 ZeroMemory(&nf, sizeof(nf)); 00140 nf.lpDecimalSep = wszDecimalSep; 00141 nf.lpThousandSep = wszThousandSep; 00142 00143 // Get system string for groups separator 00144 WCHAR wszGrouping[12]; 00145 INT cchGrouping = GetLocaleInfoW(LOCALE_USER_DEFAULT, 00146 LOCALE_SGROUPING, 00147 wszGrouping, 00148 _countof(wszGrouping)); 00149 00150 // Convert grouping specs from string to integer 00151 for (INT i = 0; i < cchGrouping; i++) 00152 { 00153 WCHAR wch = wszGrouping[i]; 00154 00155 if (wch >= L'0' && wch <= L'9') 00156 nf.Grouping = nf.Grouping * 10 + (wch - L'0'); 00157 else if (wch != L';') 00158 break; 00159 } 00160 00161 if ((nf.Grouping % 10) == 0) 00162 nf.Grouping /= 10; 00163 else 00164 nf.Grouping *= 10; 00165 00166 // Format the number 00167 INT cchResult = GetNumberFormatW(LOCALE_USER_DEFAULT, 00168 0, 00169 wszNumber, 00170 &nf, 00171 pwszResult, 00172 cchResultMax); 00173 00174 if (!cchResult) 00175 return 0; 00176 00177 // GetNumberFormatW returns number of characters including UNICODE_NULL 00178 return cchResult - 1; 00179 } 00180 00181 UINT 00182 SH_FormatByteSize(LONGLONG cbSize, LPWSTR pwszResult, UINT cchResultMax) 00183 { 00184 /* Write formated bytes count */ 00185 INT cchWritten = SH_FormatInteger(cbSize, pwszResult, cchResultMax); 00186 if (!cchWritten) 00187 return 0; 00188 00189 /* Copy " bytes" to buffer */ 00190 LPWSTR pwszEnd = pwszResult + cchWritten; 00191 size_t cchRemaining = cchResultMax - cchWritten; 00192 StringCchCopyExW(pwszEnd, cchRemaining, L" ", &pwszEnd, &cchRemaining, NULL); 00193 cchWritten = LoadStringW(shell32_hInstance, IDS_BYTES_FORMAT, pwszEnd, cchRemaining); 00194 cchRemaining -= cchWritten; 00195 00196 return cchResultMax - cchRemaining; 00197 } 00198 00199 /************************************************************************* 00200 * 00201 * SH_FormatFileSizeWithBytes 00202 * 00203 * Format a size in bytes to string. 00204 * 00205 * lpQwSize = Pointer to 64bit large integer to format 00206 * pszBuf = Buffer to fill with output string 00207 * cchBuf = size of pszBuf in characters 00208 * 00209 */ 00210 00211 LPWSTR 00212 SH_FormatFileSizeWithBytes(const PULARGE_INTEGER lpQwSize, LPWSTR pwszResult, UINT cchResultMax) 00213 { 00214 /* Format bytes in KBs, MBs etc */ 00215 if (StrFormatByteSizeW(lpQwSize->QuadPart, pwszResult, cchResultMax) == NULL) 00216 return NULL; 00217 00218 /* If there is less bytes than 1KB, we have nothing to do */ 00219 if (lpQwSize->QuadPart < 1024) 00220 return pwszResult; 00221 00222 /* Concate " (" */ 00223 UINT cchWritten = wcslen(pwszResult); 00224 LPWSTR pwszEnd = pwszResult + cchWritten; 00225 size_t cchRemaining = cchResultMax - cchWritten; 00226 StringCchCopyExW(pwszEnd, cchRemaining, L" (", &pwszEnd, &cchRemaining, 0); 00227 00228 /* Write formated bytes count */ 00229 cchWritten = SH_FormatByteSize(lpQwSize->QuadPart, pwszEnd, cchRemaining); 00230 pwszEnd += cchWritten; 00231 cchRemaining -= cchWritten; 00232 00233 /* Copy ")" to the buffer */ 00234 StringCchCopyW(pwszEnd, cchRemaining, L")"); 00235 00236 return pwszResult; 00237 } 00238 00239 /************************************************************************* 00240 * 00241 * SH_CreatePropertySheetPage [Internal] 00242 * 00243 * creates a property sheet page from an resource name 00244 * 00245 */ 00246 00247 HPROPSHEETPAGE 00248 SH_CreatePropertySheetPage(WORD wDialogId, DLGPROC pfnDlgProc, LPARAM lParam, LPCWSTR pwszTitle) 00249 { 00250 HRSRC hRes = FindResourceW(shell32_hInstance, MAKEINTRESOURCEW(wDialogId), (LPWSTR)RT_DIALOG); 00251 if (hRes == NULL) 00252 { 00253 ERR("failed to find resource id\n"); 00254 return NULL; 00255 } 00256 00257 LPVOID pTemplate = LoadResource(shell32_hInstance, hRes); 00258 if (pTemplate == NULL) 00259 { 00260 ERR("failed to load resource\n"); 00261 return NULL; 00262 } 00263 00264 PROPSHEETPAGEW Page; 00265 memset(&Page, 0x0, sizeof(PROPSHEETPAGEW)); 00266 Page.dwSize = sizeof(PROPSHEETPAGEW); 00267 Page.dwFlags = PSP_DLGINDIRECT; 00268 Page.pResource = (DLGTEMPLATE*)pTemplate; 00269 Page.pfnDlgProc = pfnDlgProc; 00270 Page.lParam = lParam; 00271 Page.pszTitle = pwszTitle; 00272 00273 if (pwszTitle) 00274 Page.dwFlags |= PSP_USETITLE; 00275 00276 return CreatePropertySheetPageW(&Page); 00277 } 00278 00279 VOID 00280 CFileDefExt::InitOpensWithField(HWND hwndDlg) 00281 { 00282 WCHAR wszBuf[MAX_PATH] = L""; 00283 WCHAR wszPath[MAX_PATH] = L""; 00284 DWORD dwSize = sizeof(wszBuf); 00285 BOOL bUnknownApp = TRUE; 00286 LPCWSTR pwszExt = PathFindExtensionW(m_wszPath); 00287 00288 if (RegGetValueW(HKEY_CLASSES_ROOT, pwszExt, L"", RRF_RT_REG_SZ, NULL, wszBuf, &dwSize) == ERROR_SUCCESS) 00289 { 00290 bUnknownApp = FALSE; 00291 StringCbCatW(wszBuf, sizeof(wszBuf), L"\\shell\\open\\command"); 00292 dwSize = sizeof(wszPath); 00293 if (RegGetValueW(HKEY_CLASSES_ROOT, wszBuf, L"", RRF_RT_REG_SZ, NULL, wszPath, &dwSize) == ERROR_SUCCESS) 00294 { 00295 /* Get path from command line */ 00296 ExpandEnvironmentStringsW(wszPath, wszBuf, _countof(wszBuf)); 00297 PathRemoveArgs(wszBuf); 00298 PathUnquoteSpacesW(wszBuf); 00299 PathSearchAndQualify(wszBuf, wszPath, _countof(wszPath)); 00300 00301 HICON hIcon; 00302 if (ExtractIconExW(wszPath, 0, NULL, &hIcon, 1)) 00303 { 00304 HWND hIconCtrl = GetDlgItem(hwndDlg, 14025); 00305 HWND hDescrCtrl = GetDlgItem(hwndDlg, 14007); 00306 ShowWindow(hIconCtrl, SW_SHOW); 00307 RECT rcIcon, rcDescr; 00308 GetWindowRect(hIconCtrl, &rcIcon); 00309 if (rcIcon.left == rcIcon.right) 00310 ERR("Icon control has invalid width: %d-%d\n", rcIcon.left, rcIcon.right); 00311 MapWindowPoints(NULL, hwndDlg, (LPPOINT)&rcIcon, 2); 00312 GetWindowRect(hDescrCtrl, &rcDescr); 00313 MapWindowPoints(NULL, hwndDlg, (LPPOINT)&rcDescr, 2); 00314 INT cxOffset = rcIcon.right + 2 - rcDescr.left; 00315 SetWindowPos(hDescrCtrl, NULL, 00316 rcDescr.left + cxOffset, rcDescr.top, 00317 rcDescr.right - rcDescr.left - cxOffset, rcDescr.bottom - rcDescr.top, 00318 SWP_NOZORDER); 00319 SendMessageW(hIconCtrl, STM_SETICON, (WPARAM)hIcon, 0); 00320 } else 00321 ERR("Failed to extract icon\n"); 00322 00323 if (PathFileExistsW(wszPath)) 00324 { 00325 /* Get file description */ 00326 CFileVersionInfo VerInfo; 00327 VerInfo.Load(wszPath); 00328 LPCWSTR pwszDescr = VerInfo.GetString(L"FileDescription"); 00329 if (pwszDescr) 00330 SetDlgItemTextW(hwndDlg, 14007, pwszDescr); 00331 else 00332 { 00333 /* File has no description - display filename */ 00334 LPWSTR pwszFilename = PathFindFileNameW(wszPath); 00335 PathRemoveExtension(pwszFilename); 00336 pwszFilename[0] = towupper(pwszFilename[0]); 00337 SetDlgItemTextW(hwndDlg, 14007, pwszFilename); 00338 } 00339 } 00340 else 00341 bUnknownApp = TRUE; 00342 } else 00343 WARN("RegGetValueW %ls failed\n", wszBuf); 00344 } else 00345 WARN("RegGetValueW %ls failed\n", pwszExt); 00346 00347 if (bUnknownApp) 00348 { 00349 /* Unknown application */ 00350 LoadStringW(shell32_hInstance, IDS_UNKNOWN_APP, wszBuf, _countof(wszBuf)); 00351 SetDlgItemTextW(hwndDlg, 14007, wszBuf); 00352 } 00353 } 00354 00355 /************************************************************************* 00356 * 00357 * SH_FileGeneralFileType [Internal] 00358 * 00359 * retrieves file extension description from registry and sets it in dialog 00360 * 00361 * TODO: retrieve file extension default icon and load it 00362 * find executable name from registry, retrieve description from executable 00363 */ 00364 00365 BOOL 00366 CFileDefExt::InitFileType(HWND hwndDlg) 00367 { 00368 TRACE("path %s\n", debugstr_w(m_wszPath)); 00369 00370 HWND hDlgCtrl = GetDlgItem(hwndDlg, 14005); 00371 if (hDlgCtrl == NULL) 00372 return FALSE; 00373 00374 /* Get file information */ 00375 SHFILEINFO fi; 00376 if (!SHGetFileInfoW(m_wszPath, 0, &fi, sizeof(fi), SHGFI_TYPENAME|SHGFI_ICON)) 00377 { 00378 ERR("SHGetFileInfoW failed for %ls (%lu)\n", m_wszPath, GetLastError()); 00379 fi.szTypeName[0] = L'\0'; 00380 fi.hIcon = NULL; 00381 } 00382 00383 LPCWSTR pwszExt = PathFindExtensionW(m_wszPath); 00384 if (pwszExt[0]) 00385 { 00386 WCHAR wszBuf[256]; 00387 00388 if (!fi.szTypeName[0]) 00389 { 00390 /* The file type is unknown, so default to string "FileExtension File" */ 00391 size_t cchRemaining = 0; 00392 LPWSTR pwszEnd = NULL; 00393 00394 StringCchPrintfExW(wszBuf, _countof(wszBuf), &pwszEnd, &cchRemaining, 0, L"%s ", pwszExt + 1); 00395 SendMessageW(hDlgCtrl, WM_GETTEXT, (WPARAM)cchRemaining, (LPARAM)pwszEnd); 00396 00397 SendMessageW(hDlgCtrl, WM_SETTEXT, (WPARAM)NULL, (LPARAM)wszBuf); 00398 } 00399 else 00400 { 00401 /* Update file type */ 00402 StringCbPrintfW(wszBuf, sizeof(wszBuf), L"%s (%s)", fi.szTypeName, pwszExt); 00403 SendMessageW(hDlgCtrl, WM_SETTEXT, (WPARAM)NULL, (LPARAM)wszBuf); 00404 } 00405 } 00406 00407 /* Update file icon */ 00408 if (fi.hIcon) 00409 SendDlgItemMessageW(hwndDlg, 14000, STM_SETICON, (WPARAM)fi.hIcon, 0); 00410 else 00411 ERR("No icon %ls\n", m_wszPath); 00412 00413 return TRUE; 00414 } 00415 00416 /************************************************************************* 00417 * 00418 * CFileDefExt::InitFilePath [Internal] 00419 * 00420 * sets file path string and filename string 00421 * 00422 */ 00423 00424 BOOL 00425 CFileDefExt::InitFilePath(HWND hwndDlg) 00426 { 00427 /* Find the filename */ 00428 WCHAR *pwszFilename = PathFindFileNameW(m_wszPath); 00429 00430 if (pwszFilename > m_wszPath) 00431 { 00432 /* Location field */ 00433 WCHAR wszLocation[MAX_PATH]; 00434 StringCchCopyNW(wszLocation, _countof(wszLocation), m_wszPath, pwszFilename - m_wszPath); 00435 PathRemoveBackslashW(wszLocation); 00436 00437 SetDlgItemTextW(hwndDlg, 14009, wszLocation); 00438 } 00439 00440 /* Filename field */ 00441 SetDlgItemTextW(hwndDlg, 14001, pwszFilename); 00442 00443 return TRUE; 00444 } 00445 00446 /************************************************************************* 00447 * 00448 * CFileDefExt::GetFileTimeString [Internal] 00449 * 00450 * formats a given LPFILETIME struct into readable user format 00451 */ 00452 00453 BOOL 00454 CFileDefExt::GetFileTimeString(LPFILETIME lpFileTime, LPWSTR pwszResult, UINT cchResult) 00455 { 00456 FILETIME ft; 00457 SYSTEMTIME st; 00458 00459 if (!FileTimeToLocalFileTime(lpFileTime, &ft) || !FileTimeToSystemTime(&ft, &st)) 00460 return FALSE; 00461 00462 size_t cchRemaining = cchResult; 00463 LPWSTR pwszEnd = pwszResult; 00464 int cchWritten = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, pwszEnd, cchRemaining); 00465 if (cchWritten) 00466 --cchWritten; // GetDateFormatW returns count with terminating zero 00467 else 00468 ERR("GetDateFormatW failed\n"); 00469 cchRemaining -= cchWritten; 00470 pwszEnd += cchWritten; 00471 00472 StringCchCopyExW(pwszEnd, cchRemaining, L", ", &pwszEnd, &cchRemaining, 0); 00473 00474 cchWritten = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, pwszEnd, cchRemaining); 00475 if (cchWritten) 00476 --cchWritten; // GetTimeFormatW returns count with terminating zero 00477 else 00478 ERR("GetTimeFormatW failed\n"); 00479 TRACE("result %s\n", debugstr_w(pwszResult)); 00480 return TRUE; 00481 } 00482 00483 /************************************************************************* 00484 * 00485 * CFileDefExt::InitFileAttr [Internal] 00486 * 00487 * retrieves file information from file and sets in dialog 00488 * 00489 */ 00490 00491 BOOL 00492 CFileDefExt::InitFileAttr(HWND hwndDlg) 00493 { 00494 WCHAR wszBuf[MAX_PATH]; 00495 00496 TRACE("InitFileAttr %ls\n", m_wszPath); 00497 00498 WIN32_FILE_ATTRIBUTE_DATA FileInfo; 00499 if (GetFileAttributesExW(m_wszPath, GetFileExInfoStandard, &FileInfo)) 00500 { 00501 /* Update attribute checkboxes */ 00502 if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY) 00503 SendDlgItemMessage(hwndDlg, 14021, BM_SETCHECK, BST_CHECKED, 0); 00504 if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) 00505 SendDlgItemMessage(hwndDlg, 14022, BM_SETCHECK, BST_CHECKED, 0); 00506 if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) 00507 SendDlgItemMessage(hwndDlg, 14023, BM_SETCHECK, BST_CHECKED, 0); 00508 00509 /* Update creation time */ 00510 if (GetFileTimeString(&FileInfo.ftCreationTime, wszBuf, _countof(wszBuf))) 00511 SetDlgItemTextW(hwndDlg, 14015, wszBuf); 00512 00513 /* For files display last access and last write time */ 00514 if (!m_bDir) 00515 { 00516 if (GetFileTimeString(&FileInfo.ftLastAccessTime, wszBuf, _countof(wszBuf))) 00517 SetDlgItemTextW(hwndDlg, 14019, wszBuf); 00518 00519 if (GetFileTimeString(&FileInfo.ftLastWriteTime, wszBuf, _countof(wszBuf))) 00520 SetDlgItemTextW(hwndDlg, 14017, wszBuf); 00521 00522 /* Update size of file */ 00523 ULARGE_INTEGER FileSize; 00524 FileSize.u.LowPart = FileInfo.nFileSizeLow; 00525 FileSize.u.HighPart = FileInfo.nFileSizeHigh; 00526 if (SH_FormatFileSizeWithBytes(&FileSize, wszBuf, _countof(wszBuf))) 00527 SetDlgItemTextW(hwndDlg, 14011, wszBuf); 00528 } 00529 } 00530 00531 if (m_bDir) 00532 { 00533 /* For directories files have to be counted */ 00534 StringCchCopyW(wszBuf, _countof(wszBuf), m_wszPath); 00535 CountFolderAndFiles(wszBuf, _countof(wszBuf)); 00536 00537 /* Update size filed */ 00538 if (SH_FormatFileSizeWithBytes(&m_DirSize, wszBuf, _countof(wszBuf))) 00539 SetDlgItemTextW(hwndDlg, 14011, wszBuf); 00540 00541 /* Display files and folders count */ 00542 WCHAR wszFormat[256]; 00543 LoadStringW(shell32_hInstance, IDS_FILE_FOLDER, wszFormat, _countof(wszFormat)); 00544 StringCchPrintfW(wszBuf, _countof(wszBuf), wszFormat, m_cFiles, m_cFolders); 00545 SetDlgItemTextW(hwndDlg, 14027, wszBuf); 00546 } 00547 00548 /* Hide Advanced button. TODO: Implement advanced dialog and enable this button if filesystem supports compression or encryption */ 00549 ShowWindow(GetDlgItem(hwndDlg, 14028), SW_HIDE); 00550 00551 return TRUE; 00552 } 00553 00554 /************************************************************************* 00555 * 00556 * CFileDefExt::InitGeneralPage [Internal] 00557 * 00558 * sets all file general properties in dialog 00559 */ 00560 00561 BOOL 00562 CFileDefExt::InitGeneralPage(HWND hwndDlg) 00563 { 00564 /* Set general text properties filename filelocation and icon */ 00565 InitFilePath(hwndDlg); 00566 00567 /* Set file type and icon */ 00568 InitFileType(hwndDlg); 00569 00570 /* Set open with application */ 00571 if (!m_bDir) 00572 { 00573 if (!PathIsExeW(m_wszPath)) 00574 InitOpensWithField(hwndDlg); 00575 else 00576 { 00577 WCHAR wszBuf[MAX_PATH]; 00578 LoadStringW(shell32_hInstance, IDS_EXE_DESCRIPTION, wszBuf, _countof(wszBuf)); 00579 SetDlgItemTextW(hwndDlg, 14006, wszBuf); 00580 ShowWindow(GetDlgItem(hwndDlg, 14024), SW_HIDE); 00581 LPCWSTR pwszDescr = m_VerInfo.GetString(L"FileDescription"); 00582 if (pwszDescr) 00583 SetDlgItemTextW(hwndDlg, 14007, pwszDescr); 00584 else 00585 { 00586 StringCbCopyW(wszBuf, sizeof(wszBuf), PathFindFileNameW(m_wszPath)); 00587 PathRemoveExtension(wszBuf); 00588 SetDlgItemTextW(hwndDlg, 14007, wszBuf); 00589 } 00590 } 00591 } 00592 00593 /* Set file created/modfied/accessed time, size and attributes */ 00594 InitFileAttr(hwndDlg); 00595 00596 return TRUE; 00597 } 00598 00599 /************************************************************************* 00600 * 00601 * CFileDefExt::GeneralPageProc 00602 * 00603 * wnd proc of 'General' property sheet page 00604 * 00605 */ 00606 00607 INT_PTR CALLBACK 00608 CFileDefExt::GeneralPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 00609 { 00610 switch (uMsg) 00611 { 00612 case WM_INITDIALOG: 00613 { 00614 LPPROPSHEETPAGEW ppsp = (LPPROPSHEETPAGEW)lParam; 00615 00616 if (ppsp == NULL || !ppsp->lParam) 00617 break; 00618 00619 TRACE("WM_INITDIALOG hwnd %p lParam %p ppsplParam %S\n", hwndDlg, lParam, ppsp->lParam); 00620 00621 CFileDefExt *pFileDefExt = (CFileDefExt*)ppsp->lParam; 00622 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pFileDefExt); 00623 pFileDefExt->InitGeneralPage(hwndDlg); 00624 break; 00625 } 00626 case WM_COMMAND: 00627 if (LOWORD(wParam) == 14024) /* Opens With - Change */ 00628 { 00629 CFileDefExt *pFileDefExt = (CFileDefExt*)GetWindowLongPtr(hwndDlg, DWLP_USER); 00630 OPENASINFO oainfo; 00631 oainfo.pcszFile = pFileDefExt->m_wszPath; 00632 oainfo.pcszClass = NULL; 00633 oainfo.oaifInFlags = OAIF_REGISTER_EXT|OAIF_FORCE_REGISTRATION; 00634 return SUCCEEDED(SHOpenWithDialog(hwndDlg, &oainfo)); 00635 } 00636 else if (LOWORD(wParam) == 14021 || LOWORD(wParam) == 14022 || LOWORD(wParam) == 14023) /* checkboxes */ 00637 PropSheet_Changed(GetParent(hwndDlg), hwndDlg); 00638 else if (LOWORD(wParam) == 14001) /* Name */ 00639 { 00640 if (HIWORD(wParam) == EN_CHANGE) 00641 PropSheet_Changed(GetParent(hwndDlg), hwndDlg); 00642 } 00643 break; 00644 case WM_NOTIFY: 00645 { 00646 LPPSHNOTIFY lppsn = (LPPSHNOTIFY)lParam; 00647 if (lppsn->hdr.code == PSN_APPLY) 00648 { 00649 CFileDefExt *pFileDefExt = (CFileDefExt*)GetWindowLongPtr(hwndDlg, DWLP_USER); 00650 00651 /* Update attributes first */ 00652 DWORD dwAttr = GetFileAttributesW(pFileDefExt->m_wszPath); 00653 if (dwAttr) 00654 { 00655 dwAttr &= ~(FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_ARCHIVE); 00656 00657 if (BST_CHECKED == SendDlgItemMessageW(hwndDlg, 14021, BM_GETCHECK, 0, 0)) 00658 dwAttr |= FILE_ATTRIBUTE_READONLY; 00659 if (BST_CHECKED == SendDlgItemMessageW(hwndDlg, 14022, BM_GETCHECK, 0, 0)) 00660 dwAttr |= FILE_ATTRIBUTE_HIDDEN; 00661 if (BST_CHECKED == SendDlgItemMessageW(hwndDlg, 14023, BM_GETCHECK, 0, 0)) 00662 dwAttr |= FILE_ATTRIBUTE_ARCHIVE; 00663 00664 if (!SetFileAttributesW(pFileDefExt->m_wszPath, dwAttr)) 00665 ERR("SetFileAttributesW failed\n"); 00666 } 00667 00668 /* Update filename now */ 00669 WCHAR wszBuf[MAX_PATH]; 00670 StringCchCopyW(wszBuf, _countof(wszBuf), pFileDefExt->m_wszPath); 00671 LPWSTR pwszFilename = PathFindFileNameW(wszBuf); 00672 UINT cchFilenameMax = _countof(wszBuf) - (pwszFilename - wszBuf); 00673 if (GetDlgItemTextW(hwndDlg, 14001, pwszFilename, cchFilenameMax)) 00674 { 00675 if (!MoveFileW(pFileDefExt->m_wszPath, wszBuf)) 00676 ERR("MoveFileW failed\n"); 00677 } 00678 00679 SetWindowLongPtr(hwndDlg, DWL_MSGRESULT, PSNRET_NOERROR); 00680 return TRUE; 00681 } 00682 break; 00683 } 00684 default: 00685 break; 00686 } 00687 00688 return FALSE; 00689 } 00690 00691 /************************************************************************* 00692 * 00693 * CFileDefExt::InitVersionPage [Internal] 00694 * 00695 * sets all file version properties in dialog 00696 */ 00697 00698 BOOL 00699 CFileDefExt::InitVersionPage(HWND hwndDlg) 00700 { 00701 /* Get fixed info */ 00702 VS_FIXEDFILEINFO *pInfo = m_VerInfo.GetFixedInfo(); 00703 if (pInfo) 00704 { 00705 WCHAR wszVersion[256]; 00706 swprintf(wszVersion, L"%u.%u.%u.%u", HIWORD(pInfo->dwFileVersionMS), 00707 LOWORD(pInfo->dwFileVersionMS), 00708 HIWORD(pInfo->dwFileVersionLS), 00709 LOWORD(pInfo->dwFileVersionLS)); 00710 TRACE("MS %x LS %x ver %s \n", pInfo->dwFileVersionMS, pInfo->dwFileVersionLS, debugstr_w(wszVersion)); 00711 SetDlgItemTextW(hwndDlg, 14001, wszVersion); 00712 } 00713 00714 /* Update labels */ 00715 SetVersionLabel(hwndDlg, 14003, L"FileDescription"); 00716 SetVersionLabel(hwndDlg, 14005, L"LegalCopyright"); 00717 00718 /* Add items to listbox */ 00719 AddVersionString(hwndDlg, L"CompanyName"); 00720 LPCWSTR pwszLang = m_VerInfo.GetLangName(); 00721 if (pwszLang) 00722 { 00723 HWND hDlgCtrl = GetDlgItem(hwndDlg, 14009); 00724 UINT Index = SendMessageW(hDlgCtrl, LB_ADDSTRING, (WPARAM)-1, (LPARAM)L"Language"); 00725 SendMessageW(hDlgCtrl, LB_SETITEMDATA, (WPARAM)Index, (LPARAM)(WCHAR *)pwszLang); 00726 } 00727 AddVersionString(hwndDlg, L"ProductName"); 00728 AddVersionString(hwndDlg, L"InternalName"); 00729 AddVersionString(hwndDlg, L"OriginalFilename"); 00730 AddVersionString(hwndDlg, L"FileVersion"); 00731 AddVersionString(hwndDlg, L"ProductVersion"); 00732 00733 /* Attach file version to dialog window */ 00734 SetWindowLongPtr(hwndDlg, DWL_USER, (LONG_PTR)this); 00735 00736 /* Select first item */ 00737 HWND hDlgCtrl = GetDlgItem(hwndDlg, 14009); 00738 SendMessageW(hDlgCtrl, LB_SETCURSEL, 0, 0); 00739 LPCWSTR pwszText = (LPCWSTR)SendMessageW(hDlgCtrl, LB_GETITEMDATA, (WPARAM)0, (LPARAM)NULL); 00740 if (pwszText && pwszText != (LPCWSTR)LB_ERR) 00741 SetDlgItemTextW(hwndDlg, 14010, pwszText); 00742 00743 return TRUE; 00744 } 00745 00746 /************************************************************************* 00747 * 00748 * CFileDefExt::SetVersionLabel [Internal] 00749 * 00750 * retrieves a version string and uses it to set label text 00751 */ 00752 00753 BOOL 00754 CFileDefExt::SetVersionLabel(HWND hwndDlg, DWORD idCtrl, LPCWSTR pwszName) 00755 { 00756 if (hwndDlg == NULL || pwszName == NULL) 00757 return FALSE; 00758 00759 LPCWSTR pwszValue = m_VerInfo.GetString(pwszName); 00760 if (pwszValue) 00761 { 00762 /* file description property */ 00763 TRACE("%s :: %s\n", debugstr_w(pwszName), debugstr_w(pwszValue)); 00764 SetDlgItemTextW(hwndDlg, idCtrl, pwszValue); 00765 return TRUE; 00766 } 00767 00768 return FALSE; 00769 } 00770 00771 /************************************************************************* 00772 * 00773 * CFileDefExt::AddVersionString [Internal] 00774 * 00775 * retrieves a version string and adds it to listbox 00776 */ 00777 00778 BOOL 00779 CFileDefExt::AddVersionString(HWND hwndDlg, LPCWSTR pwszName) 00780 { 00781 TRACE("pwszName %s, hwndDlg %p\n", debugstr_w(pwszName), hwndDlg); 00782 00783 if (hwndDlg == NULL || pwszName == NULL) 00784 return FALSE; 00785 00786 LPCWSTR pwszValue = m_VerInfo.GetString(pwszName); 00787 if (pwszValue) 00788 { 00789 /* listbox name property */ 00790 HWND hDlgCtrl = GetDlgItem(hwndDlg, 14009); 00791 TRACE("%s :: %s\n", debugstr_w(pwszName), debugstr_w(pwszValue)); 00792 UINT Index = SendMessageW(hDlgCtrl, LB_ADDSTRING, (WPARAM) -1, (LPARAM)pwszName); 00793 SendMessageW(hDlgCtrl, LB_SETITEMDATA, (WPARAM)Index, (LPARAM)(WCHAR *)pwszValue); 00794 return TRUE; 00795 } 00796 00797 return FALSE; 00798 } 00799 00800 /************************************************************************* 00801 * 00802 * CFileDefExt::VersionPageProc 00803 * 00804 * wnd proc of 'Version' property sheet page 00805 */ 00806 00807 INT_PTR CALLBACK 00808 CFileDefExt::VersionPageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 00809 { 00810 switch (uMsg) 00811 { 00812 case WM_INITDIALOG: 00813 { 00814 LPPROPSHEETPAGE ppsp = (LPPROPSHEETPAGE)lParam; 00815 00816 if (ppsp == NULL || !ppsp->lParam) 00817 break; 00818 00819 TRACE("WM_INITDIALOG hwnd %p lParam %p ppsplParam %x\n", hwndDlg, lParam, ppsp->lParam); 00820 00821 CFileDefExt *pFileDefExt = (CFileDefExt*)ppsp->lParam; 00822 return pFileDefExt->InitVersionPage(hwndDlg); 00823 } 00824 case WM_COMMAND: 00825 if (LOWORD(wParam) == 14009 && HIWORD(wParam) == LBN_SELCHANGE) 00826 { 00827 HWND hDlgCtrl = (HWND)lParam; 00828 00829 LRESULT Index = SendMessageW(hDlgCtrl, LB_GETCURSEL, (WPARAM)NULL, (LPARAM)NULL); 00830 if (Index == LB_ERR) 00831 break; 00832 00833 LPCWSTR pwszData = (LPCWSTR)SendMessageW(hDlgCtrl, LB_GETITEMDATA, (WPARAM)Index, (LPARAM)NULL); 00834 if (pwszData == NULL) 00835 break; 00836 00837 TRACE("hDlgCtrl %x string %s\n", hDlgCtrl, debugstr_w(pwszData)); 00838 SetDlgItemTextW(hwndDlg, 14010, pwszData); 00839 00840 return TRUE; 00841 } 00842 break; 00843 case WM_DESTROY: 00844 break; 00845 default: 00846 break; 00847 } 00848 00849 return FALSE; 00850 } 00851 00852 CFileDefExt::CFileDefExt(): 00853 m_bDir(FALSE), m_cFiles(0), m_cFolders(0) 00854 { 00855 m_wszPath[0] = L'\0'; 00856 m_DirSize.QuadPart = 0ull; 00857 } 00858 00859 CFileDefExt::~CFileDefExt() 00860 { 00861 00862 } 00863 00864 HRESULT WINAPI 00865 CFileDefExt::Initialize(LPCITEMIDLIST pidlFolder, IDataObject *pDataObj, HKEY hkeyProgID) 00866 { 00867 FORMATETC format; 00868 STGMEDIUM stgm; 00869 HRESULT hr; 00870 00871 TRACE("%p %p %p %p\n", this, pidlFolder, pDataObj, hkeyProgID); 00872 00873 if (!pDataObj) 00874 return E_FAIL; 00875 00876 format.cfFormat = CF_HDROP; 00877 format.ptd = NULL; 00878 format.dwAspect = DVASPECT_CONTENT; 00879 format.lindex = -1; 00880 format.tymed = TYMED_HGLOBAL; 00881 00882 hr = pDataObj->GetData(&format, &stgm); 00883 if (FAILED(hr)) 00884 return hr; 00885 00886 if (!DragQueryFileW((HDROP)stgm.hGlobal, 0, m_wszPath, _countof(m_wszPath))) 00887 { 00888 ERR("DragQueryFileW failed\n"); 00889 ReleaseStgMedium(&stgm); 00890 return E_FAIL; 00891 } 00892 00893 ReleaseStgMedium(&stgm); 00894 00895 TRACE("File properties %ls\n", m_wszPath); 00896 m_bDir = PathIsDirectoryW(m_wszPath) ? TRUE : FALSE; 00897 if (!m_bDir) 00898 m_VerInfo.Load(m_wszPath); 00899 00900 return S_OK; 00901 } 00902 00903 HRESULT WINAPI 00904 CFileDefExt::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags) 00905 { 00906 UNIMPLEMENTED; 00907 return E_NOTIMPL; 00908 } 00909 00910 HRESULT WINAPI 00911 CFileDefExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpici) 00912 { 00913 UNIMPLEMENTED; 00914 return E_NOTIMPL; 00915 } 00916 00917 HRESULT WINAPI 00918 CFileDefExt::GetCommandString(UINT_PTR idCmd, UINT uType, UINT *pwReserved, LPSTR pszName, UINT cchMax) 00919 { 00920 UNIMPLEMENTED; 00921 return E_NOTIMPL; 00922 } 00923 00924 HRESULT WINAPI 00925 CFileDefExt::AddPages(LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam) 00926 { 00927 HPROPSHEETPAGE hPage; 00928 WORD wResId = m_bDir ? IDD_FOLDER_PROPERTIES : IDD_FILE_PROPERTIES; 00929 00930 hPage = SH_CreatePropertySheetPage(wResId, 00931 GeneralPageProc, 00932 (LPARAM)this, 00933 NULL); 00934 if (hPage) 00935 pfnAddPage(hPage, lParam); 00936 00937 if (!m_bDir && GetFileVersionInfoSizeW(m_wszPath, NULL)) 00938 { 00939 hPage = SH_CreatePropertySheetPage(IDD_FILE_VERSION, 00940 VersionPageProc, 00941 (LPARAM)this, 00942 NULL); 00943 if (hPage) 00944 pfnAddPage(hPage, lParam); 00945 } 00946 00947 return S_OK; 00948 } 00949 00950 HRESULT WINAPI 00951 CFileDefExt::ReplacePage(UINT uPageID, LPFNADDPROPSHEETPAGE pfnReplacePage, LPARAM lParam) 00952 { 00953 UNIMPLEMENTED; 00954 return E_NOTIMPL; 00955 } 00956 00957 HRESULT WINAPI 00958 CFileDefExt::SetSite(IUnknown *punk) 00959 { 00960 UNIMPLEMENTED; 00961 return E_NOTIMPL; 00962 } 00963 00964 HRESULT WINAPI 00965 CFileDefExt::GetSite(REFIID iid, void **ppvSite) 00966 { 00967 UNIMPLEMENTED; 00968 return E_NOTIMPL; 00969 } 00970 00971 BOOL 00972 CFileDefExt::CountFolderAndFiles(LPWSTR pwszBuf, UINT cchBufMax) 00973 { 00974 /* Find filename position */ 00975 UINT cchBuf = wcslen(pwszBuf); 00976 WCHAR *pwszFilename = pwszBuf + cchBuf; 00977 size_t cchFilenameMax = cchBufMax - cchBuf; 00978 if (!cchFilenameMax) 00979 return FALSE; 00980 *(pwszFilename++) = '\\'; 00981 --cchFilenameMax; 00982 00983 /* Find all files, FIXME: shouldn't be "*"? */ 00984 StringCchCopyW(pwszFilename, cchFilenameMax, L"*"); 00985 00986 WIN32_FIND_DATAW wfd; 00987 HANDLE hFind = FindFirstFileW(pwszBuf, &wfd); 00988 if (hFind == INVALID_HANDLE_VALUE) 00989 { 00990 ERR("FindFirstFileW %ls failed\n", pwszBuf); 00991 return FALSE; 00992 } 00993 00994 do 00995 { 00996 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 00997 { 00998 /* Don't process "." and ".." items */ 00999 if (!wcscmp(wfd.cFileName, L".") || !wcscmp(wfd.cFileName, L"..")) 01000 continue; 01001 01002 ++m_cFolders; 01003 01004 StringCchCopyW(pwszFilename, cchFilenameMax, wfd.cFileName); 01005 CountFolderAndFiles(pwszBuf, cchBufMax); 01006 } 01007 else 01008 { 01009 m_cFiles++; 01010 01011 ULARGE_INTEGER FileSize; 01012 FileSize.u.LowPart = wfd.nFileSizeLow; 01013 FileSize.u.HighPart = wfd.nFileSizeHigh; 01014 m_DirSize.QuadPart += FileSize.QuadPart; 01015 } 01016 } while(FindNextFileW(hFind, &wfd)); 01017 01018 FindClose(hFind); 01019 return TRUE; 01020 } Generated on Sun May 27 2012 04:26:20 for ReactOS by
1.7.6.1
|