mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1125 lines
35 KiB
1125 lines
35 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1993 - 1995.
|
|
//
|
|
// File: mulprsht.c
|
|
//
|
|
// Contents: Code for multi and single file property sheet page
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
|
#include "shellprv.h"
|
|
#pragma hdrstop
|
|
|
|
#ifdef WINNT
|
|
#include <wfext.h>
|
|
#include <shcompui.h> // NT Explorer compression UI.
|
|
#endif
|
|
|
|
// allow the user to change the system and archive bits on files.
|
|
// I can't think of any reason to allow this
|
|
// #define CHANGE_SYS
|
|
|
|
// version.c
|
|
extern void AddVersionPage(LPCTSTR szFilePath, LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM lParam);
|
|
// link.c
|
|
extern void AddLinkPage(HIDA hida, LPCTSTR szFilePath, LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM lParam);
|
|
|
|
const TCHAR c_szBackslash[] = TEXT("\\");
|
|
|
|
#define IDT_SIZE 1
|
|
|
|
|
|
typedef struct { // fpsp
|
|
PROPSHEETPAGE psp;
|
|
HWND hDlg;
|
|
HIDA hida;
|
|
HANDLE hThread; // for computing folder size
|
|
TCHAR szPath[MAX_PATH];
|
|
|
|
FOLDERCONTENTSINFO fci;
|
|
#ifdef WINNT
|
|
int iInitCompressedState; // 0 = uncompressed.
|
|
// 1 = compressed.
|
|
// 2 = mix
|
|
// -1 = compression not supported.
|
|
#endif
|
|
HWND hLocationTip; // window handle for location tooltip
|
|
TCHAR szTipText[MAX_PATH]; // Tip text for > 80 characters
|
|
} FILEPROPSHEETPAGE;
|
|
|
|
void _CheckFlagDlgButton(HWND hDlg, int id, DWORD uFlag, DWORD uFlagsAND, DWORD uFlagsOR)
|
|
{
|
|
int i;
|
|
|
|
uFlagsAND &= uFlag; // isolate the bit
|
|
uFlagsOR &= uFlag; // isolate the bit
|
|
|
|
if (uFlagsAND ^ uFlagsOR)
|
|
i = 2; // not EQUAL, tri state
|
|
else if (uFlagsAND & uFlag)
|
|
i = 1; // on, set
|
|
else
|
|
i = 0; // off, not set
|
|
|
|
// make the control try state by setting the style bits
|
|
if (i == 2)
|
|
{
|
|
// BUGBUG: SetWindowStyle() should work, "buttons" don't
|
|
// listen to WM_STYLECHANGING messages, they should
|
|
SendDlgItemMessage(hDlg, id, BM_SETSTYLE, BS_AUTO3STATE, 0);
|
|
}
|
|
|
|
CheckDlgButton(hDlg, id, i);
|
|
}
|
|
|
|
|
|
void _UpdateSizeCount(FILEPROPSHEETPAGE * pfpsp)
|
|
{
|
|
TCHAR szNum[20], szNum1[32];
|
|
|
|
LPTSTR pszFmt = NULL;
|
|
NUMBERFMT NumFmt;
|
|
|
|
NumFmt.NumDigits = 0;
|
|
NumFmt.LeadingZero = 0;
|
|
|
|
Int64ToString(pfpsp->fci.iSize,
|
|
szNum1,
|
|
ARRAYSIZE(szNum1),
|
|
TRUE,
|
|
&NumFmt,
|
|
NUMFMT_IDIGITS | NUMFMT_ILZERO);
|
|
|
|
pszFmt = ShellConstructMessageString(HINST_THISDLL, MAKEINTRESOURCE(IDS_FOLDERSIZE),
|
|
ShortSizeFormat64(pfpsp->fci.iSize, szNum), szNum1);
|
|
|
|
if (pszFmt) {
|
|
SetDlgItemText(pfpsp->hDlg, IDD_FILESIZE, pszFmt);
|
|
SHFree(pszFmt);
|
|
}
|
|
|
|
pszFmt = ShellConstructMessageString(HINST_THISDLL, MAKEINTRESOURCE(IDS_NUMFILES),
|
|
AddCommas(pfpsp->fci.cFiles, szNum), AddCommas(pfpsp->fci.cFolders, szNum1));
|
|
if (pszFmt) {
|
|
SetDlgItemText(pfpsp->hDlg, IDD_CONTAINS, pszFmt);
|
|
SHFree(pszFmt);
|
|
}
|
|
|
|
if (!pfpsp->fci.bContinue)
|
|
KillTimer(pfpsp->hDlg, IDT_SIZE);
|
|
}
|
|
|
|
void _FolderSize(LPCTSTR pszDir, FOLDERCONTENTSINFO * pfci)
|
|
{
|
|
TCHAR szPath[MAX_PATH];
|
|
|
|
|
|
if (!pfci->bContinue)
|
|
return;
|
|
|
|
pfci->cFolders++;
|
|
|
|
if (PathCombine(szPath, pszDir, c_szStarDotStar))
|
|
{
|
|
HANDLE hfind = FindFirstFile(szPath, &pfci->fd);
|
|
if (hfind != INVALID_HANDLE_VALUE)
|
|
{
|
|
do
|
|
{
|
|
if (!PathIsDotOrDotDot(pfci->fd.cFileName))
|
|
{
|
|
if (pfci->fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
{
|
|
PathCombine(szPath, pszDir, pfci->fd.cFileName);
|
|
_FolderSize(szPath, pfci);
|
|
}
|
|
else
|
|
{
|
|
ULARGE_INTEGER ulTemp;
|
|
ulTemp.LowPart = pfci->fd.nFileSizeLow;
|
|
ulTemp.HighPart = pfci->fd.nFileSizeHigh;
|
|
|
|
pfci->iSize += ulTemp.QuadPart;
|
|
pfci->cFiles++;
|
|
}
|
|
}
|
|
} while (FindNextFile(hfind, &pfci->fd) && pfci->bContinue);
|
|
|
|
FindClose(hfind);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
DWORD CALLBACK _SizeThreadProc(FILEPROPSHEETPAGE *pfpsp)
|
|
{
|
|
UINT iItem;
|
|
TCHAR szPath[MAX_PATH];
|
|
|
|
pfpsp->fci.iSize = 0;
|
|
pfpsp->fci.cFiles = 0;
|
|
|
|
for (iItem = 0; CFSFolder_FillFindData(pfpsp->hida, iItem, szPath, &pfpsp->fci.fd) && pfpsp->fci.bContinue; iItem++)
|
|
{
|
|
if (pfpsp->fci.fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
{
|
|
_FolderSize(szPath, &pfpsp->fci);
|
|
}
|
|
else
|
|
{ // file selected
|
|
ULARGE_INTEGER ulTemp;
|
|
ulTemp.LowPart = pfpsp->fci.fd.nFileSizeLow;
|
|
ulTemp.HighPart = pfpsp->fci.fd.nFileSizeHigh;
|
|
|
|
pfpsp->fci.iSize += ulTemp.QuadPart;
|
|
pfpsp->fci.cFiles++;
|
|
}
|
|
}
|
|
|
|
pfpsp->fci.bContinue = FALSE;
|
|
return 0;
|
|
}
|
|
|
|
|
|
void _CreateSizeThread(FILEPROPSHEETPAGE * pfpsp, int cFolders)
|
|
{
|
|
if (pfpsp->fci.bContinue && !pfpsp->hThread)
|
|
{
|
|
DWORD idThread;
|
|
|
|
pfpsp->fci.cFolders = cFolders; // initial count
|
|
|
|
pfpsp->hThread = CreateThread(NULL, 0, _SizeThreadProc, pfpsp, 0, &idThread);
|
|
if (pfpsp->hThread)
|
|
SetTimer(pfpsp->hDlg, IDT_SIZE, 250, NULL);
|
|
}
|
|
}
|
|
|
|
|
|
void _KillSizeThread(FILEPROPSHEETPAGE * pfpsp)
|
|
{
|
|
if (pfpsp && pfpsp->hThread)
|
|
{
|
|
if (pfpsp->fci.bContinue)
|
|
{
|
|
// still running!
|
|
pfpsp->fci.bContinue = FALSE;
|
|
// We will attempt to wait up to 2 seconds for the thread to terminate
|
|
if (WaitForSingleObject(pfpsp->hThread, 2000) == WAIT_TIMEOUT)
|
|
// Blow it away!
|
|
TerminateThread(pfpsp->hThread, (DWORD)-1);
|
|
}
|
|
|
|
CloseHandle(pfpsp->hThread);
|
|
pfpsp->hThread = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Descriptions:
|
|
// This function fills fields of the multiple object property sheet.
|
|
//
|
|
BOOL _UpdateMultiplePrsht(FILEPROPSHEETPAGE * pfpsp)
|
|
{
|
|
SHFILEINFO sfi;
|
|
TCHAR szBuffer[MAX_PATH];
|
|
TCHAR szType[MAX_PATH];
|
|
TCHAR szDirPath[MAX_PATH];
|
|
int iItem;
|
|
BOOL fMultipleType;
|
|
BOOL fSameLocation;
|
|
DWORD dwFlagsAND, dwFlagsOR;
|
|
|
|
szDirPath[0] = 0;
|
|
szType[0] = 0;
|
|
fMultipleType = FALSE;
|
|
fSameLocation = TRUE;
|
|
|
|
dwFlagsOR = 0; // start all clear
|
|
dwFlagsAND = (DWORD)-1; // start all set
|
|
|
|
#ifdef WINNT
|
|
pfpsp->iInitCompressedState = 0; // Assume compression support.
|
|
#endif
|
|
|
|
// For all the selected files add up the sizes and compare the types
|
|
for (iItem = 0; CFSFolder_FillFindData(pfpsp->hida, iItem, szBuffer, NULL); iItem++)
|
|
{
|
|
DWORD dwFileAttributes = GetFileAttributes(szBuffer);
|
|
// Don't rely on the ones coming from the structure as we do not
|
|
// get notifications of attributes changing...
|
|
|
|
dwFlagsAND &= dwFileAttributes;
|
|
dwFlagsOR |= dwFileAttributes;
|
|
|
|
// process types only if we haven't already found that
|
|
// there are many types
|
|
if (!fMultipleType)
|
|
{
|
|
SHGetFileInfo((LPTSTR)IDA_GetIDListPtr((LPIDA)GlobalLock(pfpsp->hida), iItem), 0,
|
|
&sfi, SIZEOF(sfi), SHGFI_PIDL|SHGFI_TYPENAME);
|
|
#ifdef DEBUG
|
|
{
|
|
SHFILEINFO x;
|
|
SHGetFileInfo(szBuffer, 0, &x, SIZEOF(x), SHGFI_TYPENAME);
|
|
Assert(lstrcmp(x.szTypeName, sfi.szTypeName)==0);
|
|
}
|
|
#endif
|
|
if (szType[0] == TEXT('\0'))
|
|
lstrcpy(szType, sfi.szTypeName);
|
|
else
|
|
fMultipleType = lstrcmp(szType, sfi.szTypeName) != 0;
|
|
}
|
|
|
|
#ifdef WINNT
|
|
{
|
|
TCHAR szRootName[_MAX_PATH + 1];
|
|
DWORD dwVolumeFlags = 0;
|
|
|
|
//
|
|
// If we still haven't encountered a non-compressible volume,
|
|
// check the volume for this file.
|
|
//
|
|
if (pfpsp->iInitCompressedState != -1)
|
|
{
|
|
lstrcpy(szRootName, szBuffer);
|
|
PathStripToRoot(szRootName);
|
|
// GetVolumeInformation requires a trailing backslash. Append
|
|
// one if this is a UNC path.
|
|
if (PathIsUNC(szRootName))
|
|
{
|
|
lstrcat(szRootName, c_szBackslash);
|
|
}
|
|
if (!GetVolumeInformation(szRootName, NULL, 0, NULL, NULL, &dwVolumeFlags, NULL, 0) ||
|
|
!(dwVolumeFlags & FS_FILE_COMPRESSION))
|
|
{
|
|
//
|
|
// Found a non-compressible volume. This prevents
|
|
// display of the "Compress" checkbox.
|
|
//
|
|
pfpsp->iInitCompressedState = -1;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (fSameLocation)
|
|
{
|
|
PathRemoveFileSpec(szBuffer);
|
|
|
|
if (szDirPath[0] == TEXT('\0'))
|
|
lstrcpy(szDirPath, szBuffer);
|
|
else
|
|
fSameLocation = (lstrcmpi(szDirPath, szBuffer) == 0);
|
|
}
|
|
}
|
|
|
|
if (fMultipleType)
|
|
{
|
|
LoadString(HINST_THISDLL, IDS_MULTIPLETYPES, szBuffer, ARRAYSIZE(szBuffer));
|
|
}
|
|
else
|
|
{
|
|
LoadString(HINST_THISDLL, IDS_ALLOFTYPE, szBuffer, ARRAYSIZE(szBuffer));
|
|
lstrcat(szBuffer, szType);
|
|
}
|
|
SetDlgItemText(pfpsp->hDlg, IDD_FILETYPE, szBuffer);
|
|
|
|
if (fSameLocation)
|
|
{
|
|
LoadString(HINST_THISDLL, IDS_ALLIN, szBuffer, ARRAYSIZE(szBuffer));
|
|
lstrcat(szBuffer, szDirPath);
|
|
lstrcpy(pfpsp->szPath, szDirPath);
|
|
}
|
|
else
|
|
LoadString(HINST_THISDLL, IDS_VARFOLDERS, szBuffer, ARRAYSIZE(szBuffer));
|
|
|
|
SetDlgItemText(pfpsp->hDlg, IDD_LOCATION, szBuffer);
|
|
|
|
// attributes
|
|
|
|
_CheckFlagDlgButton(pfpsp->hDlg, IDD_READONLY, FILE_ATTRIBUTE_READONLY, dwFlagsAND, dwFlagsOR);
|
|
_CheckFlagDlgButton(pfpsp->hDlg, IDD_HIDDEN, FILE_ATTRIBUTE_HIDDEN, dwFlagsAND, dwFlagsOR);
|
|
_CheckFlagDlgButton(pfpsp->hDlg, IDD_ARCHIVE, FILE_ATTRIBUTE_ARCHIVE, dwFlagsAND, dwFlagsOR);
|
|
_CheckFlagDlgButton(pfpsp->hDlg, IDD_SYSTEM, FILE_ATTRIBUTE_SYSTEM, dwFlagsAND, dwFlagsOR);
|
|
|
|
#ifdef WINNT
|
|
//
|
|
// If the volume supports compression based upon the previous checks,
|
|
// show the "Compressed" checkbox and configure it so that it correctly
|
|
// indicates the compression state of the selected files.
|
|
//
|
|
if (pfpsp->iInitCompressedState != -1)
|
|
{
|
|
_CheckFlagDlgButton(pfpsp->hDlg, IDD_COMPRESSED, FILE_ATTRIBUTE_COMPRESSED, dwFlagsAND, dwFlagsOR);
|
|
pfpsp->iInitCompressedState = Button_GetCheck(GetDlgItem(pfpsp->hDlg, IDD_COMPRESSED));
|
|
ShowWindow(GetDlgItem(pfpsp->hDlg, IDD_COMPRESSED), SW_SHOW);
|
|
}
|
|
#else
|
|
//
|
|
// Win95 Multiple File property page dialog template doesn't have a
|
|
// "Compressed" checkbox control.
|
|
//
|
|
#endif
|
|
|
|
// size and # of files
|
|
_CreateSizeThread(pfpsp, 0);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// Sets attributes of the files.
|
|
//
|
|
BOOL _SetAttributes(FILEPROPSHEETPAGE * pfpsp)
|
|
{
|
|
DWORD dwFlagsChange, dwFlagsNew, state;
|
|
UINT iItem;
|
|
BOOL fSomethingChanged = FALSE;
|
|
TCHAR szPath[MAX_PATH];
|
|
|
|
dwFlagsChange = FILE_ATTRIBUTE_DIRECTORY;
|
|
dwFlagsNew = 0;
|
|
|
|
if ((state = IsDlgButtonChecked(pfpsp->hDlg, IDD_READONLY)) < 2) {
|
|
dwFlagsChange |= FILE_ATTRIBUTE_READONLY;
|
|
if (state == 1)
|
|
dwFlagsNew |= FILE_ATTRIBUTE_READONLY;
|
|
}
|
|
|
|
if ((state = IsDlgButtonChecked(pfpsp->hDlg, IDD_HIDDEN)) < 2) {
|
|
dwFlagsChange |= FILE_ATTRIBUTE_HIDDEN;
|
|
if (state == 1)
|
|
dwFlagsNew |= FILE_ATTRIBUTE_HIDDEN;
|
|
}
|
|
|
|
if ((state = IsDlgButtonChecked(pfpsp->hDlg, IDD_ARCHIVE)) < 2) {
|
|
dwFlagsChange |= FILE_ATTRIBUTE_ARCHIVE;
|
|
if (state == 1)
|
|
dwFlagsNew |= FILE_ATTRIBUTE_ARCHIVE;
|
|
}
|
|
|
|
|
|
#if CHANGE_SYS // changing the archaive and system bit is disabled
|
|
if ((state = IsDlgButtonChecked(pfpsp->hDlg, IDD_SYSTEM)) < 2) {
|
|
dwFlagsChange |= FILE_ATTRIBUTE_SYSTEM;
|
|
if (state == 1)
|
|
dwFlagsNew |= FILE_ATTRIBUTE_SYSTEM;
|
|
}
|
|
#endif
|
|
|
|
// For all the selected files add up the sizes and compare the types
|
|
for (iItem = 0; CFSFolder_FillFindData(pfpsp->hida, iItem, szPath, NULL); iItem++)
|
|
{
|
|
DWORD dwFlags;
|
|
DWORD dwFileAttributes = GetFileAttributes(szPath);
|
|
|
|
// Do not depend on the cached values of the attribues from the pidl.
|
|
// instead we should get them from the file. if it returns ffffffff
|
|
// there was an error, so jump to the next item...
|
|
if (dwFileAttributes == (DWORD)-1)
|
|
continue; // try the next one...
|
|
|
|
dwFlags = (dwFlagsChange & dwFlagsNew) | (~dwFlagsChange & dwFileAttributes);
|
|
if (dwFlags ^ (dwFileAttributes & ~FILE_ATTRIBUTE_DIRECTORY))
|
|
{
|
|
Assert((dwFlags & FILE_ATTRIBUTE_DIRECTORY) == 0);
|
|
|
|
fSomethingChanged = TRUE;
|
|
while (!SetFileAttributes(szPath, dwFlags))
|
|
{
|
|
if (ShellMessageBox(HINST_THISDLL, GetParent(pfpsp->hDlg),
|
|
MAKEINTRESOURCE(IDS_CANNOTSETATTRIBUTES), NULL,
|
|
MB_RETRYCANCEL | MB_ICONHAND, PathFindFileName(szPath)) != IDRETRY)
|
|
{
|
|
fSomethingChanged = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
//
|
|
// Tell the shell that attributes have changed.
|
|
// This will update explorer's attributes column.
|
|
// If a directory, remove trailing backslash.
|
|
//
|
|
PathRemoveBackslash(szPath);
|
|
SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_PATH, szPath, NULL);
|
|
}
|
|
}
|
|
|
|
if (fSomethingChanged)
|
|
PropSheet_CancelToClose(GetParent(pfpsp->hDlg));
|
|
|
|
|
|
#ifdef WINNT
|
|
//
|
|
// If drive supports compression.
|
|
//
|
|
if (pfpsp->iInitCompressedState != -1)
|
|
{
|
|
int CompressCbxState = Button_GetCheck(GetDlgItem(pfpsp->hDlg, IDD_COMPRESSED));
|
|
|
|
//
|
|
// If compress checkbox state has changed, and it is not
|
|
// indeterminate, load the compression UI code and compress/uncompress
|
|
// the file(s).
|
|
//
|
|
if (CompressCbxState != pfpsp->iInitCompressedState &&
|
|
CompressCbxState < 2)
|
|
{
|
|
HINSTANCE hinstCompressDll = LoadLibrary(SZ_SHCOMPUI_DLLNAME);
|
|
|
|
if (hinstCompressDll != NULL)
|
|
{
|
|
FARPROC lpfCompress = GetProcAddress((HMODULE)hinstCompressDll,
|
|
SZ_COMPRESS_PROCNAME);
|
|
if (lpfCompress)
|
|
{
|
|
UINT iItem = 0;
|
|
TCHAR szPath[_MAX_PATH + 1];
|
|
SCCA_CONTEXT Context;
|
|
|
|
SCCA_CONTEXT_INIT(&Context);
|
|
|
|
//
|
|
// Call compression function for each selected file or directory.
|
|
//
|
|
for (iItem = 0; CFSFolder_FillFindData(pfpsp->hida, iItem, szPath, NULL); iItem++)
|
|
{
|
|
//
|
|
// Compress/Uncompress file with full UI.
|
|
// If error occured or user cancelled operation, stop iteration.
|
|
//
|
|
if (!(*lpfCompress)(pfpsp->hDlg, szPath, &Context, CompressCbxState, TRUE))
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
Assert(0); // Something wrong with export of function.
|
|
|
|
FreeLibrary(hinstCompressDll);
|
|
}
|
|
else
|
|
{
|
|
ShellMessageBox(HINST_THISDLL, pfpsp->hDlg,
|
|
MAKEINTRESOURCE(IDS_NOSHCOMPUI),
|
|
MAKEINTRESOURCE(IDS_EXPLORER_NAME),
|
|
MB_OK | MB_ICONEXCLAMATION);
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
//
|
|
// Win95 Multiple File property page dialog template doesn't have a
|
|
// "Compressed" checkbox control.
|
|
//
|
|
#endif
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// Descriptions:
|
|
// This is the dialog procedure for multiple object property sheet.
|
|
//
|
|
|
|
const DWORD aGeneralHelpIds[] = {
|
|
IDD_LINE_1, NO_HELP,
|
|
IDD_LINE_2, NO_HELP,
|
|
IDD_LINE_3, NO_HELP,
|
|
IDD_CONTAINS_TXT, IDH_FPROP_FOLDER_CONTAINS,
|
|
IDD_CONTAINS, IDH_FPROP_FOLDER_CONTAINS,
|
|
IDD_ITEMICON, IDH_FPROP_GEN_ICON,
|
|
IDD_NAME, IDH_FPROP_GEN_NAME,
|
|
IDD_FILETYPE_TXT, IDH_FPROP_GEN_TYPE,
|
|
IDD_FILETYPE, IDH_FPROP_GEN_TYPE,
|
|
IDD_FILESIZE_TXT, IDH_FPROP_GEN_SIZE,
|
|
IDD_FILESIZE, IDH_FPROP_GEN_SIZE,
|
|
IDD_FILESIZE_COMPRESSED, IDH_FPROP_GEN_COMPRESSED_SIZE,
|
|
IDD_FILESIZE_COMPRESSED_TXT, IDH_FPROP_GEN_COMPRESSED_SIZE,
|
|
IDD_LOCATION_TXT, IDH_FPROP_GEN_LOCATION,
|
|
IDD_LOCATION, IDH_FPROP_GEN_LOCATION,
|
|
IDD_FILENAME_TXT, IDH_FPROP_GEN_DOSNAME,
|
|
IDD_FILENAME, IDH_FPROP_GEN_DOSNAME,
|
|
IDD_CREATED_TXT, IDH_FPROP_GEN_DATE_CREATED,
|
|
IDD_CREATED, IDH_FPROP_GEN_DATE_CREATED, // BUGBUG
|
|
IDD_LASTMODIFIED_TXT, IDH_FPROP_GEN_LASTCHANGE,
|
|
IDD_LASTMODIFIED, IDH_FPROP_GEN_LASTCHANGE,
|
|
IDD_LASTACCESSED_TXT, IDH_FPROP_GEN_LASTACCESS,
|
|
IDD_LASTACCESSED, IDH_FPROP_GEN_LASTACCESS,
|
|
IDD_READONLY, IDH_FPROP_GEN_READONLY,
|
|
IDD_HIDDEN, IDH_FPROP_GEN_HIDDEN,
|
|
IDD_ARCHIVE, IDH_FPROP_GEN_ARCHIVE,
|
|
IDD_SYSTEM, IDH_FPROP_GEN_SYSTEM,
|
|
IDD_COMPRESSED, IDH_FPROP_GEN_COMPRESSED,
|
|
IDD_ATTR_GROUPBOX, IDH_COMM_GROUPBOX,
|
|
0, 0
|
|
};
|
|
|
|
const DWORD aMultiPropHelpIds[] = {
|
|
IDD_LINE_1, NO_HELP,
|
|
IDD_LINE_2, NO_HELP,
|
|
IDD_ATTR_GROUPBOX, IDH_COMM_GROUPBOX,
|
|
IDD_ITEMICON, IDH_FPROP_GEN_ICON,
|
|
IDD_CONTAINS, IDH_MULTPROP_NAME,
|
|
IDD_FILETYPE_TXT, IDH_FPROP_GEN_TYPE,
|
|
IDD_FILETYPE, IDH_FPROP_GEN_TYPE,
|
|
IDD_FILESIZE_TXT, IDH_FPROP_GEN_SIZE,
|
|
IDD_FILESIZE, IDH_FPROP_GEN_SIZE,
|
|
IDD_FILESIZE_COMPRESSED, IDH_FPROP_GEN_COMPRESSED_SIZE,
|
|
IDD_FILESIZE_COMPRESSED_TXT, IDH_FPROP_GEN_COMPRESSED_SIZE,
|
|
IDD_LOCATION_TXT, IDH_FPROP_GEN_LOCATION,
|
|
IDD_LOCATION, IDH_FPROP_GEN_LOCATION,
|
|
IDD_READONLY, IDH_FPROP_GEN_READONLY,
|
|
IDD_HIDDEN, IDH_FPROP_GEN_HIDDEN,
|
|
IDD_ARCHIVE, IDH_FPROP_GEN_ARCHIVE,
|
|
IDD_SYSTEM, IDH_FPROP_GEN_SYSTEM,
|
|
IDD_ATTR_GROUPBOX, IDH_COMM_GROUPBOX,
|
|
IDD_COMPRESSED, IDH_FPROP_GEN_COMPRESSED,
|
|
0, 0
|
|
};
|
|
|
|
TCHAR const c_szSToolTipsClass[] = TOOLTIPS_CLASS;
|
|
|
|
HWND AddLocationToolTips(FILEPROPSHEETPAGE * pfpsp)
|
|
{
|
|
TOOLINFO ti;
|
|
HWND hwndTT = CreateWindow(c_szSToolTipsClass, c_szNULL, WS_POPUP | TTS_NOPREFIX,
|
|
CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
|
|
pfpsp->hDlg, NULL, HINST_THISDLL, NULL);
|
|
|
|
ti.cbSize = SIZEOF(ti);
|
|
ti.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
|
|
ti.hwnd = pfpsp->hDlg;
|
|
ti.uId = (UINT)GetDlgItem(pfpsp->hDlg, IDD_LOCATION);
|
|
ti.lpszText = LPSTR_TEXTCALLBACK;
|
|
ti.hinst = HINST_THISDLL;
|
|
SendMessage(hwndTT, TTM_ADDTOOL, 0, (LPARAM)(LPTOOLINFO)&ti);
|
|
|
|
return hwndTT;
|
|
}
|
|
|
|
BOOL CALLBACK _MultiplePrshtDlgProc(HWND hDlg, UINT uMessage, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
FILEPROPSHEETPAGE * pfpsp = (FILEPROPSHEETPAGE *)GetWindowLong(hDlg, DWL_USER);
|
|
|
|
switch (uMessage) {
|
|
case WM_INITDIALOG:
|
|
SetWindowLong(hDlg, DWL_USER, lParam);
|
|
pfpsp = (FILEPROPSHEETPAGE *)lParam;
|
|
pfpsp->hDlg = hDlg;
|
|
pfpsp->hLocationTip = AddLocationToolTips(pfpsp);
|
|
break;
|
|
|
|
case WM_HELP:
|
|
WinHelp((HWND) ((LPHELPINFO) lParam)->hItemHandle, NULL, HELP_WM_HELP,
|
|
(DWORD)(LPTSTR) aMultiPropHelpIds);
|
|
break;
|
|
|
|
case WM_CONTEXTMENU: // right mouse click
|
|
WinHelp((HWND)wParam, NULL, HELP_CONTEXTMENU, (DWORD)(LPTSTR) aMultiPropHelpIds);
|
|
return TRUE;
|
|
|
|
case WM_TIMER:
|
|
_UpdateSizeCount(pfpsp);
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
_KillSizeThread(pfpsp);
|
|
DestroyWindow (pfpsp->hLocationTip);
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch (GET_WM_COMMAND_ID(wParam, lParam)) {
|
|
case IDD_READONLY:
|
|
case IDD_HIDDEN:
|
|
case IDD_ARCHIVE:
|
|
#ifdef CHANGE_SYS
|
|
case IDD_SYSTEM:
|
|
#endif
|
|
#ifdef WINNT
|
|
case IDD_COMPRESSED:
|
|
#endif
|
|
if (GET_WM_COMMAND_CMD(wParam, lParam) == BN_CLICKED)
|
|
SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0L);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
|
|
case WM_NOTIFY:
|
|
switch (((NMHDR *)lParam)->code) {
|
|
case PSN_SETACTIVE:
|
|
_UpdateMultiplePrsht(pfpsp);
|
|
break;
|
|
|
|
case PSN_APPLY:
|
|
_SetAttributes(pfpsp);
|
|
break;
|
|
|
|
case TTN_NEEDTEXT:
|
|
#define lpttt ((LPTOOLTIPTEXT)lParam)
|
|
lpttt->lpszText = pfpsp->szPath;
|
|
#undef lpttt
|
|
break;
|
|
|
|
default:
|
|
return(FALSE);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// in:
|
|
// hdlg
|
|
// id text control id
|
|
// pftUTC UTC time time to be set
|
|
|
|
void SetDateTimeText(HWND hdlg, int id, const FILETIME *pftUTC)
|
|
{
|
|
SYSTEMTIME st;
|
|
TCHAR szBuf[80], szTmp[64];
|
|
|
|
if (!IsNullTime(pftUTC)) {
|
|
FILETIME ft;
|
|
|
|
FileTimeToLocalFileTime(pftUTC, &ft); // get in local time
|
|
FileTimeToSystemTime(&ft, &st);
|
|
|
|
GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, szBuf, ARRAYSIZE(szBuf));
|
|
|
|
// don't bother with the time if it is NULL
|
|
if (st.wHour || st.wMinute || st.wSecond) {
|
|
lstrcat(szBuf, c_szSpace);
|
|
GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, szTmp, ARRAYSIZE(szTmp));
|
|
lstrcat(szBuf, szTmp);
|
|
}
|
|
|
|
SetDlgItemText(hdlg, id, szBuf);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Descriptions:
|
|
// This function fills fields of the "general" dialog box (a page of
|
|
// a property sheet) with attributes of the associated file.
|
|
//
|
|
|
|
BOOL _UpdateFilePrsht(FILEPROPSHEETPAGE * pfpsp)
|
|
{
|
|
HANDLE hfind;
|
|
TCHAR szBuffer[MAX_PATH];
|
|
TCHAR szNum[MAX_COMMA_AS_K_SIZE];
|
|
TCHAR szNum1[MAX_COMMA_NUMBER_SIZE];
|
|
WIN32_FIND_DATA fd;
|
|
SHFILEINFO sfi;
|
|
|
|
|
|
// fd is filled in with info from the pidl, but this
|
|
// does not contain all the datse/time information so hit the disk here.
|
|
hfind = FindFirstFile(pfpsp->szPath, &fd);
|
|
Assert(hfind != INVALID_HANDLE_VALUE);
|
|
if (hfind == INVALID_HANDLE_VALUE)
|
|
{
|
|
// if this failed we should clear out some values as to not show
|
|
// garbage on the screen.
|
|
_fmemset(&fd, TEXT('\0'), SIZEOF(fd));
|
|
}
|
|
else
|
|
FindClose(hfind);
|
|
|
|
// get info about the file.
|
|
SHGetFileInfo(pfpsp->szPath, fd.dwFileAttributes, &sfi, SIZEOF(sfi),
|
|
SHGFI_USEFILEATTRIBUTES|
|
|
SHGFI_ICON|SHGFI_LARGEICON|
|
|
SHGFI_DISPLAYNAME|
|
|
SHGFI_TYPENAME);
|
|
|
|
// .ani cursor hack!
|
|
if (lstrcmpi(PathFindExtension(pfpsp->szPath), TEXT(".ani")) == 0)
|
|
{
|
|
HICON hIcon = (HICON)LoadImage(NULL, pfpsp->szPath, IMAGE_ICON, 0, 0, LR_LOADFROMFILE);
|
|
if (hIcon)
|
|
{
|
|
if (sfi.hIcon)
|
|
DestroyIcon(sfi.hIcon);
|
|
sfi.hIcon = hIcon;
|
|
}
|
|
}
|
|
|
|
// icon
|
|
if (sfi.hIcon)
|
|
{
|
|
if (sfi.hIcon = (HICON)SendDlgItemMessage(pfpsp->hDlg, IDD_ITEMICON, STM_SETICON, (WPARAM)sfi.hIcon, 0L))
|
|
DestroyIcon(sfi.hIcon);
|
|
}
|
|
|
|
// type
|
|
SetDlgItemText(pfpsp->hDlg, IDD_FILETYPE, sfi.szTypeName);
|
|
|
|
// use the display name, not the raw dos name
|
|
SetDlgItemText(pfpsp->hDlg, IDD_NAME, sfi.szDisplayName);
|
|
|
|
// dos name
|
|
SetDlgItemText(pfpsp->hDlg, IDD_FILENAME, fd.cAlternateFileName[0] ?
|
|
fd.cAlternateFileName : fd.cFileName);
|
|
|
|
// attributes
|
|
if (fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
|
|
CheckDlgButton(pfpsp->hDlg, IDD_READONLY, 1);
|
|
if (fd.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE)
|
|
CheckDlgButton(pfpsp->hDlg, IDD_ARCHIVE, 1);
|
|
if (fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
|
|
CheckDlgButton(pfpsp->hDlg, IDD_HIDDEN, 1);
|
|
if (fd.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)
|
|
CheckDlgButton(pfpsp->hDlg, IDD_SYSTEM, 1);
|
|
|
|
#ifdef WINNT
|
|
{
|
|
DWORD dwVolumeFlags = 0;
|
|
TCHAR szRootName[_MAX_DIR + 1];
|
|
|
|
//
|
|
// If file's volume doesn't support compression, hide the "Compressed" checkbox,
|
|
// and the compressed file size display.
|
|
// If compression is supported, check/uncheck the box to indicate compression
|
|
// state of the file. Also add a "Compressed Size:" field to the dialog.
|
|
//
|
|
pfpsp->iInitCompressedState = -1; // Assume compression not supported.
|
|
lstrcpy(szRootName, pfpsp->szPath);
|
|
PathStripToRoot(szRootName);
|
|
// GetVolumeInformation requires a trailing backslash. Append
|
|
// one if this is a UNC path.
|
|
if (PathIsUNC(szRootName))
|
|
{
|
|
lstrcat(szRootName, c_szBackslash);
|
|
}
|
|
if (GetVolumeInformation(szRootName, NULL, 0, NULL, NULL, &dwVolumeFlags, NULL, 0) &&
|
|
(dwVolumeFlags & FS_FILE_COMPRESSION))
|
|
{
|
|
//
|
|
// Update the "Compress" checkbox to indicate file's compressed state.
|
|
// Updated for both files and directories.
|
|
//
|
|
ShowWindow(GetDlgItem(pfpsp->hDlg, IDD_COMPRESSED), SW_SHOW);
|
|
if (fd.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED)
|
|
pfpsp->iInitCompressedState = 1;
|
|
else
|
|
pfpsp->iInitCompressedState = 0;
|
|
|
|
CheckDlgButton(pfpsp->hDlg, IDD_COMPRESSED, pfpsp->iInitCompressedState);
|
|
|
|
if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
|
{
|
|
//
|
|
// File is not a directory.
|
|
// Configure the "Compressed Size:" text control.
|
|
//
|
|
LPTSTR pszSizeText = NULL;
|
|
if (fd.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED)
|
|
{
|
|
//
|
|
// File is compressed. Display compressed size.
|
|
//
|
|
LARGE_INTEGER nCompressedSize;
|
|
nCompressedSize.LowPart = GetCompressedFileSize(pfpsp->szPath, &nCompressedSize.HighPart);
|
|
|
|
pszSizeText = ShellConstructMessageString(HINST_THISDLL, MAKEINTRESOURCE(IDS_SIZEANDBYTES),
|
|
ShortSizeFormat64(nCompressedSize.QuadPart, szNum),
|
|
AddCommas64(nCompressedSize.QuadPart, szNum1));
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// File is not compressed. Display "File is not compressed".
|
|
//
|
|
pszSizeText = ShellConstructMessageString(HINST_THISDLL,
|
|
MAKEINTRESOURCE(IDS_FILENOTCOMPRESSED));
|
|
}
|
|
|
|
if (pszSizeText)
|
|
{
|
|
SetDlgItemText(pfpsp->hDlg, IDD_FILESIZE_COMPRESSED, pszSizeText);
|
|
SHFree(pszSizeText);
|
|
pszSizeText = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#else
|
|
//
|
|
// Win95 doesn't use the DLG_FILEPROP_COMPSIZE dialog nor the "Compressed"
|
|
// checkbox control.
|
|
//
|
|
#endif
|
|
|
|
|
|
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
{
|
|
// date and time
|
|
SetDateTimeText(pfpsp->hDlg, IDD_CREATED, &fd.ftCreationTime);
|
|
|
|
// file size
|
|
_CreateSizeThread(pfpsp, -1); // exclude this folder
|
|
}
|
|
else
|
|
{
|
|
ULARGE_INTEGER uli;
|
|
LPTSTR pszFmt;
|
|
|
|
uli.LowPart = fd.nFileSizeLow;
|
|
uli.HighPart = fd.nFileSizeHigh;
|
|
|
|
// size
|
|
pszFmt = ShellConstructMessageString(HINST_THISDLL, MAKEINTRESOURCE(IDS_SIZEANDBYTES),
|
|
ShortSizeFormat64(uli.QuadPart, szNum),
|
|
AddCommas64(uli.QuadPart, szNum1));
|
|
if (pszFmt)
|
|
{
|
|
SetDlgItemText(pfpsp->hDlg, IDD_FILESIZE, pszFmt);
|
|
SHFree(pszFmt);
|
|
pszFmt = NULL;
|
|
}
|
|
|
|
// date and time
|
|
SetDateTimeText(pfpsp->hDlg, IDD_CREATED, &fd.ftCreationTime);
|
|
SetDateTimeText(pfpsp->hDlg, IDD_LASTMODIFIED, &fd.ftLastWriteTime);
|
|
SetDateTimeText(pfpsp->hDlg, IDD_LASTACCESSED, &fd.ftLastAccessTime);
|
|
}
|
|
|
|
// the folder this file is in (location). Full path to folder.
|
|
lstrcpy(szBuffer, pfpsp->szPath);
|
|
PathRemoveFileSpec(szBuffer);
|
|
SetDlgItemText(pfpsp->hDlg, IDD_LOCATION, szBuffer);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// Descriptions:
|
|
// This is the dialog procedure for the "general" page of a property sheet.
|
|
//
|
|
|
|
BOOL CALLBACK _SingleFilePrshtDlgProc(HWND hDlg, UINT uMessage, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
FILEPROPSHEETPAGE * pfpsp = (FILEPROPSHEETPAGE *)GetWindowLong(hDlg, DWL_USER);
|
|
|
|
switch (uMessage) {
|
|
case WM_INITDIALOG:
|
|
// REVIEW, we should store more state info here, for example
|
|
// the hIcon being displayed and the FILEINFO pointer, not just
|
|
// the file name ptr
|
|
SetWindowLong(hDlg, DWL_USER, lParam);
|
|
pfpsp = (FILEPROPSHEETPAGE *)lParam;
|
|
pfpsp->hDlg = hDlg;
|
|
pfpsp->hLocationTip = AddLocationToolTips(pfpsp);
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
{
|
|
HICON hIcon = (HICON)SendDlgItemMessage(hDlg, IDD_ITEMICON, STM_GETICON, 0, 0L);
|
|
if (hIcon)
|
|
DestroyIcon(hIcon);
|
|
|
|
_KillSizeThread(pfpsp);
|
|
DestroyWindow (pfpsp->hLocationTip);
|
|
break;
|
|
}
|
|
|
|
case WM_TIMER:
|
|
_UpdateSizeCount(pfpsp);
|
|
break;
|
|
|
|
case WM_HELP:
|
|
WinHelp((HWND) ((LPHELPINFO) lParam)->hItemHandle, NULL, HELP_WM_HELP,
|
|
(DWORD)(LPTSTR) aGeneralHelpIds);
|
|
break;
|
|
|
|
case WM_CONTEXTMENU: // right mouse click
|
|
WinHelp((HWND)wParam, NULL, HELP_CONTEXTMENU, (DWORD)(LPTSTR) aGeneralHelpIds);
|
|
return TRUE;
|
|
|
|
case WM_COMMAND:
|
|
switch (GET_WM_COMMAND_ID(wParam, lParam)) {
|
|
case IDD_READONLY:
|
|
case IDD_HIDDEN:
|
|
case IDD_ARCHIVE:
|
|
case IDD_SYSTEM:
|
|
#ifdef WINNT
|
|
case IDD_COMPRESSED:
|
|
#endif
|
|
|
|
if (GET_WM_COMMAND_CMD(wParam, lParam) == BN_CLICKED)
|
|
SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0L);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case WM_NOTIFY:
|
|
switch (((NMHDR *)lParam)->code) {
|
|
case PSN_SETACTIVE:
|
|
_UpdateFilePrsht(pfpsp);
|
|
break;
|
|
|
|
case PSN_APPLY:
|
|
_SetAttributes(pfpsp);
|
|
break;
|
|
|
|
case TTN_NEEDTEXT:
|
|
{
|
|
#define lpttt ((LPTOOLTIPTEXT)lParam)
|
|
lstrcpyn(pfpsp->szTipText, pfpsp->szPath, ARRAYSIZE(pfpsp->szTipText));
|
|
PathRemoveFileSpec(pfpsp->szTipText);
|
|
lpttt->lpszText = pfpsp->szTipText;
|
|
break;
|
|
#undef lpttt
|
|
}
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//
|
|
// Descriptions:
|
|
// This function creates a property sheet object for the "general" page
|
|
// which shows file system attributes.
|
|
//
|
|
// Arguments:
|
|
// hDrop -- specifies the file(s)
|
|
// lpfnAddPage -- Specifies the callback function.
|
|
// lParam -- Specifies the lParam to be passed to the callback.
|
|
//
|
|
// Returns:
|
|
// TRUE if it added any pages
|
|
//
|
|
// History:
|
|
// 12-31-92 SatoNa Created
|
|
//
|
|
BOOL WINAPI FileSystem_AddPages(LPVOID lp, LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM lParam)
|
|
{
|
|
LPDATAOBJECT pdtobj = lp;
|
|
HIDA hida;
|
|
BOOL bResult = FALSE;
|
|
HPROPSHEETPAGE hpage;
|
|
FILEPROPSHEETPAGE fpsp;
|
|
STGMEDIUM medium;
|
|
FORMATETC fmte = {g_cfHIDA, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
|
|
|
|
if (FAILED(pdtobj->lpVtbl->GetData(pdtobj, &fmte, &medium)))
|
|
return FALSE;
|
|
|
|
hida = (HIDA)medium.hGlobal;
|
|
fpsp.psp.dwSize = SIZEOF(fpsp); // extra data
|
|
fpsp.psp.dwFlags = PSP_DEFAULT;
|
|
fpsp.psp.hInstance = HINST_THISDLL;
|
|
// fpsp.psp.lParam = 0; // unused
|
|
fpsp.hida = hida;
|
|
fpsp.fci.bContinue = TRUE;
|
|
fpsp.hThread = NULL;
|
|
fpsp.szPath[0] = 0;
|
|
fpsp.hThread = NULL;
|
|
|
|
if (HIDA_GetCount(hida) == 1) // single file?
|
|
{
|
|
// get most of the data we will need (the date/time stuff is not filled in)
|
|
if (CFSFolder_FillFindData(hida, 0, fpsp.szPath, &fpsp.fci.fd))
|
|
{
|
|
if (fpsp.fci.fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
fpsp.psp.pszTemplate = MAKEINTRESOURCE(DLG_FOLDERPROP);
|
|
else
|
|
#ifdef WINNT
|
|
{
|
|
//
|
|
// This really clutters up this section of code but it's the only place
|
|
// we can select the dialog template to use. The NT Shell UI is required
|
|
// to show Compressed File Size on files from volumes that support
|
|
// file-based compression.
|
|
//
|
|
TCHAR szRootName[_MAX_PATH + 1];
|
|
DWORD dwFlags = 0;
|
|
|
|
lstrcpy(szRootName, fpsp.szPath);
|
|
PathStripToRoot(szRootName);
|
|
// GetVolumeInformation requires a trailing backslash. Append
|
|
// one if this is a UNC path.
|
|
if (PathIsUNC(szRootName))
|
|
{
|
|
lstrcat(szRootName, c_szBackslash);
|
|
}
|
|
if (GetVolumeInformation(szRootName, NULL, 0, NULL, NULL, &dwFlags, NULL, 0) &&
|
|
(dwFlags & FS_FILE_COMPRESSION))
|
|
{
|
|
fpsp.psp.pszTemplate = MAKEINTRESOURCE(DLG_FILEPROP_COMPSIZE);
|
|
}
|
|
else
|
|
fpsp.psp.pszTemplate = MAKEINTRESOURCE(DLG_FILEPROP);
|
|
}
|
|
#else
|
|
fpsp.psp.pszTemplate = MAKEINTRESOURCE(DLG_FILEPROP);
|
|
#endif
|
|
|
|
fpsp.psp.pfnDlgProc = _SingleFilePrshtDlgProc,
|
|
|
|
hpage = CreatePropertySheetPage(&fpsp.psp);
|
|
if (hpage)
|
|
{
|
|
bResult = lpfnAddPage(hpage, lParam);
|
|
if (bResult)
|
|
{
|
|
AddVersionPage(fpsp.szPath, lpfnAddPage, lParam);
|
|
AddLinkPage(hida, fpsp.szPath, lpfnAddPage, lParam);
|
|
}
|
|
else
|
|
DestroyPropertySheetPage(hpage);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Create a property sheet page for multiple files.
|
|
//
|
|
fpsp.psp.pszTemplate = MAKEINTRESOURCE(DLG_FILEMULTPROP);
|
|
fpsp.psp.pfnDlgProc = _MultiplePrshtDlgProc,
|
|
|
|
hpage = CreatePropertySheetPage(&fpsp.psp);
|
|
if (hpage) {
|
|
bResult = lpfnAddPage(hpage, lParam);
|
|
if (!bResult)
|
|
DestroyPropertySheetPage(hpage);
|
|
}
|
|
}
|
|
|
|
SHReleaseStgMedium(&medium);
|
|
|
|
return bResult;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
//
|
|
// Type checking
|
|
//
|
|
const LPFNADDPROPSHEETPAGES s_lpfnFileSystemGetPages = FileSystem_AddPages;
|
|
#endif
|
|
|