[SHELL32]
[reactos.git] / reactos / dll / win32 / shell32 / folder_options.c
index a85938b..0e8ccbf 100644 (file)
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#include <string.h>
-
-#define COBJMACROS
-#define NONAMELESSUNION
-#define NONAMELESSSTRUCT
-#include "winerror.h"
-#include "wine/debug.h"
-
-#include "windef.h"
-#include "wingdi.h"
-#include "pidl.h"
-#include "undocshell.h"
-#include "shlobj.h"
-#include "objbase.h"
-#include "commdlg.h"
-
-#include "shell32_main.h"
-#include "shellfolder.h"
-#include "shresdef.h"
-#include "stdio.h"
-#include "shlwapi.h"
+#include <precomp.h>
+
 
 WINE_DEFAULT_DEBUG_CHANNEL (fprop);
+#define MAX_PROPERTY_SHEET_PAGE (32)
 
 /// Folder Options:
 /// CLASSKEY = HKEY_CLASSES_ROOT\CLSID\{6DFD7C5C-2451-11d3-A299-00C04F8EF6AF}
@@ -50,6 +32,66 @@ WINE_DEFAULT_DEBUG_CHANNEL (fprop);
 
 /// ShellFolder Attributes: 0x0
 
+typedef struct
+{
+   DWORD cFiles;
+   DWORD cFolder;
+   LARGE_INTEGER bSize;
+   HWND hwndDlg;
+   WCHAR szFolderPath[MAX_PATH];
+}FOLDER_PROPERTIES_CONTEXT, *PFOLDER_PROPERTIES_CONTEXT;
+
+typedef struct
+{
+    WCHAR FileExtension[30];
+    WCHAR FileDescription[100];
+    WCHAR ClassKey[MAX_PATH];
+}FOLDER_FILE_TYPE_ENTRY, *PFOLDER_FILE_TYPE_ENTRY;
+
+typedef struct
+{
+   LPCWSTR szKeyName;
+   UINT ResourceID;
+}FOLDER_VIEW_ENTRY, PFOLDER_VIEW_ENTRY;
+/*
+static FOLDER_VIEW_ENTRY s_Options[] =
+{
+    { L"AlwaysShowMenus", IDS_ALWAYSSHOWMENUS },
+    { L"AutoCheckSelect", -1 }, 
+    { L"ClassicViewState", -1 }, 
+    { L"DontPrettyPath",  -1 },
+    { L"Filter", -1 },
+    { L"FolderContentsInfoTip", IDS_FOLDERCONTENTSTIP },
+    { L"FriendlyTree", -1 },
+    { L"Hidden", -1, },
+    { L"HideFileExt", IDS_HIDEFILEEXT },
+    { L"HideIcons", -1},
+    { L"IconsOnly", -1},
+    { L"ListviewAlphaSelect", -1},
+    { L"ListviewShadow", -1},
+    { L"ListviewWatermark", -1},
+    { L"MapNetDrvBtn", -1},
+    { L"PersistBrowsers", -1},
+    { L"SeperateProcess", IDS_SEPERATEPROCESS},
+    { L"ServerAdminUI", -1},
+    { L"SharingWizardOn", IDS_USESHAREWIZARD},
+    { L"ShowCompColor", IDS_COMPCOLOR},
+    { L"ShowInfoTip", IDS_SHOWINFOTIP},
+    { L"ShowPreviewHandlers", -1},
+    { L"ShowSuperHidden", IDS_HIDEOSFILES},
+    { L"ShowTypeOverlay", -1},
+    { L"Start_ShowMyGames", -1},
+    { L"StartMenuInit", -1},
+    { L"SuperHidden", -1},
+    { L"TypeAhead", -1},
+    { L"Webview", -1},
+    { NULL, -1}
+
+};
+*/
+
+HPSXA WINAPI SHCreatePropSheetExtArrayEx(HKEY hKey, LPCWSTR pszSubKey, UINT max_iface, IDataObject *pDataObj);
+
 INT_PTR
 CALLBACK
 FolderOptionsGeneralDlg(
@@ -65,6 +107,35 @@ FolderOptionsGeneralDlg(
     return FALSE;
 }
 
+static 
+VOID
+InitializeFolderOptionsListCtrl(HWND hwndDlg)
+{
+    RECT clientRect;
+    LVCOLUMNW col;
+    WCHAR szName[50];
+    HWND hDlgCtrl;
+
+       hDlgCtrl = GetDlgItem(hwndDlg, 14003);
+
+    if (!LoadStringW(shell32_hInstance, IDS_COLUMN_EXTENSION, szName, sizeof(szName) / sizeof(WCHAR)))
+        szName[0] = 0;
+    szName[(sizeof(szName)/sizeof(WCHAR))-1] = 0;
+
+    GetClientRect(hDlgCtrl, &clientRect);
+    ZeroMemory(&col, sizeof(LV_COLUMN));
+    col.mask      = LVCF_SUBITEM | LVCF_WIDTH | LVCF_FMT;
+    col.iSubItem  = 0;
+    col.pszText = szName;
+    col.fmt = LVCFMT_LEFT;
+    col.cx        = (clientRect.right - clientRect.left) - GetSystemMetrics(SM_CXVSCROLL);
+    (void)SendMessageW(hDlgCtrl, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
+
+
+
+}
+
+
 INT_PTR
 CALLBACK
 FolderOptionsViewDlg(
@@ -74,23 +145,316 @@ FolderOptionsViewDlg(
     LPARAM lParam
 )
 {
+    switch(uMsg)
+    {
+        case WM_INITDIALOG:
+            InitializeFolderOptionsListCtrl(hwndDlg);
+            return TRUE;
+    }
+
+    return FALSE;
+
+}
+
+VOID
+InitializeFileTypesListCtrlColumns(HWND hDlgCtrl)
+{
+    RECT clientRect;
+    LVCOLUMNW col;
+    WCHAR szName[50];
+    DWORD dwStyle;
+    int columnSize = 140;
+
 
+    if (!LoadStringW(shell32_hInstance, IDS_COLUMN_EXTENSION, szName, sizeof(szName) / sizeof(WCHAR)))
+    {
+        /* default to english */
+        wcscpy(szName, L"Extensions");
+    }
 
+    /* make sure its null terminated */
+    szName[(sizeof(szName)/sizeof(WCHAR))-1] = 0;
 
-    return FALSE;
+    GetClientRect(hDlgCtrl, &clientRect);
+    ZeroMemory(&col, sizeof(LV_COLUMN));
+    columnSize = 140; //FIXME
+    col.iSubItem   = 0;
+    col.mask      = LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM | LVCF_FMT;
+    col.fmt = LVCFMT_FIXED_WIDTH;
+    col.cx         = columnSize | LVCFMT_LEFT;
+    col.cchTextMax = wcslen(szName);
+    col.pszText    = szName;
+    (void)SendMessageW(hDlgCtrl, LVM_INSERTCOLUMNW, 0, (LPARAM)&col);
+
+    if (!LoadStringW(shell32_hInstance, IDS_FILE_TYPES, szName, sizeof(szName) / sizeof(WCHAR)))
+    {
+        /* default to english */
+        wcscpy(szName, L"FileTypes");
+    }
+
+   col.iSubItem   = 1;
+   col.cx         = clientRect.right - clientRect.left - columnSize;
+   col.cchTextMax = wcslen(szName);
+   col.pszText    = szName;
+   (void)SendMessageW(hDlgCtrl, LVM_INSERTCOLUMNW, 1, (LPARAM)&col);
+
+   /* set full select style */
+   dwStyle = (DWORD) SendMessage(hDlgCtrl, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
+   dwStyle = dwStyle | LVS_EX_FULLROWSELECT;
+   SendMessage(hDlgCtrl, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, dwStyle);
+
+}
+
+INT
+FindItem(HWND hDlgCtrl, WCHAR * ItemName)
+{
+    LVFINDINFOW findInfo;
+    ZeroMemory(&findInfo, sizeof(LVFINDINFOW));
+
+    findInfo.flags = LVFI_STRING;
+    findInfo.psz = ItemName;
+    return ListView_FindItem(hDlgCtrl, 0, &findInfo);
+}
+
+VOID
+InsertFileType(HWND hDlgCtrl, WCHAR * szName, PINT iItem, WCHAR * szFile)
+{
+    PFOLDER_FILE_TYPE_ENTRY Entry;
+    HKEY hKey;
+    LVITEMW lvItem;
+    DWORD dwSize;
+
+    if (szName[0] != L'.')
+    {
+        /* FIXME handle URL protocol handlers */
+        return;
+    }
+    /* allocate file type entry */
+    Entry = (PFOLDER_FILE_TYPE_ENTRY)HeapAlloc(GetProcessHeap(), 0, sizeof(FOLDER_FILE_TYPE_ENTRY));
+
+    if (!Entry)
+        return;
+
+    /* open key */
+    if (RegOpenKeyExW(HKEY_CLASSES_ROOT, szName, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
+        return;
+
+    /* FIXME check for duplicates */
+
+    /* query for the default key */
+    dwSize = sizeof(Entry->ClassKey);
+    if (RegQueryValueExW(hKey, NULL, NULL, NULL, (LPBYTE)Entry->ClassKey, &dwSize) != ERROR_SUCCESS)
+    {
+         /* no link available */
+         Entry->ClassKey[0] = 0;
+    }
+
+    if (Entry->ClassKey[0])
+    {
+        HKEY hTemp;
+        /* try open linked key */
+        if (RegOpenKeyExW(HKEY_CLASSES_ROOT, Entry->ClassKey, 0, KEY_READ, &hTemp) == ERROR_SUCCESS)
+        {
+            /* use linked key */
+            RegCloseKey(hKey);
+            hKey = hTemp;
+        }
+    }
+
+    /* read friendly type name */
+    if (RegLoadMUIStringW(hKey, L"FriendlyTypeName", Entry->FileDescription, sizeof(Entry->FileDescription), NULL, 0, NULL) != ERROR_SUCCESS)
+    {
+        /* read file description */
+        dwSize = sizeof(Entry->FileDescription);
+        Entry->FileDescription[0] = 0;
+
+        /* read default key */
+        RegQueryValueExW(hKey, NULL, NULL, NULL, (LPBYTE)Entry->FileDescription, &dwSize);
+    }
+
+    /* close key */
+    RegCloseKey(hKey);
+
+    /* convert extension to upper case */
+    wcscpy(Entry->FileExtension, szName);
+    _wcsupr(Entry->FileExtension);
+
+    if (!Entry->FileDescription[0])
+    {
+        /* construct default 'FileExtensionFile' */
+        wcscpy(Entry->FileDescription, &Entry->FileExtension[1]);
+        wcscat(Entry->FileDescription, L" ");
+        wcscat(Entry->FileDescription, szFile);
+    }
+
+    ZeroMemory(&lvItem, sizeof(LVITEMW));
+    lvItem.mask = LVIF_TEXT | LVIF_PARAM;
+    lvItem.iSubItem = 0;
+    lvItem.pszText = &Entry->FileExtension[1];
+    lvItem.iItem = *iItem;
+    lvItem.lParam = (LPARAM)Entry;
+    (void)SendMessageW(hDlgCtrl, LVM_INSERTITEMW, 0, (LPARAM)&lvItem);
+
+    ZeroMemory(&lvItem, sizeof(LVITEMW));
+    lvItem.mask = LVIF_TEXT;
+    lvItem.pszText = Entry->FileDescription;
+    lvItem.iItem = *iItem;
+    lvItem.iSubItem = 1;
+
+    (void)SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&lvItem);
+    (*iItem)++;
+}
+
+int
+CALLBACK
+ListViewCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
+{
+    PFOLDER_FILE_TYPE_ENTRY Entry1, Entry2;
+
+    Entry1 = (PFOLDER_FILE_TYPE_ENTRY)lParam1;
+    Entry2 = (PFOLDER_FILE_TYPE_ENTRY)lParam2;
+
+    return wcsicmp(Entry1->FileExtension, Entry2->FileExtension);
+}
+
+BOOL
+InitializeFileTypesListCtrl(HWND hwndDlg)
+{
+    HWND hDlgCtrl;
+    DWORD dwIndex = 0;
+    WCHAR szName[50];
+    WCHAR szFile[100];
+    DWORD dwName;
+    LVITEMW lvItem;
+    INT iItem = 0;
+
+    hDlgCtrl = GetDlgItem(hwndDlg, 14000);
+    InitializeFileTypesListCtrlColumns(hDlgCtrl);
+
+    szFile[0] = 0;
+    if (!LoadStringW(shell32_hInstance, IDS_SHV_COLUMN1, szFile, sizeof(szFile) / sizeof(WCHAR)))
+    {
+        /* default to english */
+        wcscpy(szFile, L"File");
+    }
+    szFile[(sizeof(szFile)/sizeof(WCHAR))-1] = 0;
+
+    dwName = sizeof(szName) / sizeof(WCHAR);
+
+    while(RegEnumKeyExW(HKEY_CLASSES_ROOT, dwIndex++, szName, &dwName, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
+    {
+        InsertFileType(hDlgCtrl, szName, &iItem, szFile);
+        dwName = sizeof(szName) / sizeof(WCHAR);
+    }
+
+    /* sort list */
+    ListView_SortItems(hDlgCtrl, ListViewCompareProc, NULL);
+
+    /* select first item */
+    ZeroMemory(&lvItem, sizeof(LVITEMW));
+    lvItem.mask = LVIF_STATE;
+    lvItem.stateMask = (UINT)-1;
+    lvItem.state = LVIS_FOCUSED|LVIS_SELECTED;
+    lvItem.iItem = 0;
+    (void)SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&lvItem);
+
+    return TRUE;
+}
+
+PFOLDER_FILE_TYPE_ENTRY
+FindSelectedItem(
+    HWND hDlgCtrl)
+{
+    UINT Count, Index;
+    LVITEMW lvItem;
+
+    Count = ListView_GetItemCount(hDlgCtrl);
+
+    for (Index = 0; Index < Count; Index++)
+    {
+        ZeroMemory(&lvItem, sizeof(LVITEM));
+        lvItem.mask = LVIF_PARAM | LVIF_STATE;
+        lvItem.iItem = Index;
+        lvItem.stateMask = (UINT)-1;
+
+        if (ListView_GetItem(hDlgCtrl, &lvItem))
+        {
+            if (lvItem.state & LVIS_SELECTED)
+               return (PFOLDER_FILE_TYPE_ENTRY)lvItem.lParam;
+        }
+    }
+
+    return NULL;
 }
 
+
 INT_PTR
 CALLBACK
 FolderOptionsFileTypesDlg(
     HWND hwndDlg,
     UINT uMsg,
     WPARAM wParam,
-    LPARAM lParam
-)
+    LPARAM lParam)
 {
+    LPNMLISTVIEW lppl;
+    LVITEMW lvItem;
+    WCHAR Buffer[200], FormatBuffer[100];
+    PFOLDER_FILE_TYPE_ENTRY pItem;
+    OPENASINFO Info;
+
+    switch(uMsg)
+    {
+        case WM_INITDIALOG:
+            InitializeFileTypesListCtrl(hwndDlg);
+            return TRUE;
+        case WM_COMMAND:
+            switch(LOWORD(wParam))
+            {
+                case 14006:
+                    pItem = FindSelectedItem(GetDlgItem(hwndDlg, 14000));
+                    if (pItem)
+                    {
+                        Info.oaifInFlags = OAIF_ALLOW_REGISTRATION | OAIF_REGISTER_EXT;
+                        Info.pcszClass = pItem->FileExtension;
+                        SHOpenWithDialog(hwndDlg, &Info);
+                    }
+                    break;
+            }
+
+            break;
+       case WM_NOTIFY:
+            lppl = (LPNMLISTVIEW) lParam;
+
+            if (lppl->hdr.code == LVN_ITEMCHANGING)
+            {
+                    ZeroMemory(&lvItem, sizeof(LVITEM));
+                    lvItem.mask = LVIF_PARAM;
+                    lvItem.iItem = lppl->iItem;
+                    if (!SendMessageW(lppl->hdr.hwndFrom, LVM_GETITEMW, 0, (LPARAM)&lvItem))
+                        return TRUE;
 
+                    pItem = (PFOLDER_FILE_TYPE_ENTRY)lvItem.lParam;
+                    if (!pItem)
+                        return TRUE;
 
+                    if (!(lppl->uOldState & LVIS_FOCUSED) && (lppl->uNewState & LVIS_FOCUSED))
+                    {
+                        /* new focused item */
+                        if (!LoadStringW(shell32_hInstance, IDS_FILE_DETAILS, FormatBuffer, sizeof(FormatBuffer) / sizeof(WCHAR)))
+                        {
+                            /* use default english format string */
+                            wcscpy(FormatBuffer, L"Details for '%s' extension");
+                        }
+
+                        /* format buffer */
+                        swprintf(Buffer, FormatBuffer, &pItem->FileExtension[1]);
+                        /* update dialog */
+                        SendDlgItemMessageW(hwndDlg, 14003, WM_SETTEXT, 0, (LPARAM)Buffer);
+                    }
+           }
+           break;
+    }
 
     return FALSE;
 }
@@ -102,7 +466,7 @@ ShowFolderOptionsDialog(HWND hWnd, HINSTANCE hInst)
     PROPSHEETHEADERW pinfo;
     HPROPSHEETPAGE hppages[3];
     HPROPSHEETPAGE hpage;
-       UINT num_pages = 0;
+    UINT num_pages = 0;
     WCHAR szOptions[100];
 
     hpage = SH_CreatePropertySheetPage("FOLDER_OPTIONS_GENERAL_DLG", FolderOptionsGeneralDlg, 0, NULL);
@@ -116,14 +480,14 @@ ShowFolderOptionsDialog(HWND hWnd, HINSTANCE hInst)
     hpage = SH_CreatePropertySheetPage("FOLDER_OPTIONS_FILETYPES_DLG", FolderOptionsFileTypesDlg, 0, NULL);
     if (hpage)
         hppages[num_pages++] = hpage;
-    
+
     szOptions[0] = L'\0';
-    LoadStringW(hInst, IDS_FOLDER_OPTIONS, szOptions, sizeof(szOptions) / sizeof(WCHAR));
-    szOptions[99] = L'\0';
-    
+    LoadStringW(shell32_hInstance, IDS_FOLDER_OPTIONS, szOptions, sizeof(szOptions) / sizeof(WCHAR));
+    szOptions[(sizeof(szOptions)/sizeof(WCHAR))-1] = L'\0';
+
     memset(&pinfo, 0x0, sizeof(PROPSHEETHEADERW));
     pinfo.dwSize = sizeof(PROPSHEETHEADERW);
-    pinfo.dwFlags = PSH_NOCONTEXTHELP | PSH_PROPTITLE;
+    pinfo.dwFlags = PSH_NOCONTEXTHELP;
     pinfo.nPages = num_pages;
     pinfo.u3.phpage = hppages;
     pinfo.pszCaption = szOptions;
@@ -172,5 +536,284 @@ VOID WINAPI Options_RunDLLW(HWND hWnd, HINSTANCE hInst, LPCWSTR cmd, DWORD nCmdS
     Options_RunDLLCommon(hWnd, hInst, StrToIntW(cmd), nCmdShow);
 }
 
+static
+DWORD WINAPI
+CountFolderAndFiles(LPVOID lParam)
+{
+    WIN32_FIND_DATAW FindData;
+    HANDLE hFile;
+    UINT Length;
+    LPWSTR pOffset;
+    BOOL ret;
+    PFOLDER_PROPERTIES_CONTEXT pContext = (PFOLDER_PROPERTIES_CONTEXT) lParam;
+
+    pOffset = PathAddBackslashW(pContext->szFolderPath);
+    if (!pOffset)
+       return 0;
+
+    Length = pOffset - pContext->szFolderPath;
+
+    wcscpy(pOffset, L"*.*");
+    hFile = FindFirstFileW(pContext->szFolderPath, &FindData);
+    if (hFile == INVALID_HANDLE_VALUE)
+       return 0;
+
+    do
+    {
+        ret = FindNextFileW(hFile, &FindData);
+        if (ret)
+        {
+            if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+            {
+                if (FindData.cFileName[0] == L'.' && FindData.cFileName[1] == L'.' &&
+                    FindData.cFileName[2] == L'\0')
+                    continue;
+
+                pContext->cFolder++;
+                wcscpy(pOffset, FindData.cFileName);
+                CountFolderAndFiles((LPVOID)pContext);
+                pOffset[0] = L'\0';
+            }
+            else
+            {
+                pContext->cFiles++;
+                pContext->bSize.u.LowPart += FindData.nFileSizeLow;
+                pContext->bSize.u.HighPart += FindData.nFileSizeHigh;
+            }  
+        }
+        else if (GetLastError() == ERROR_NO_MORE_FILES)
+        {
+            break;
+        }
+    }while(1);
+
+    FindClose(hFile);
+    return 1;
+}
+
+static
+VOID
+InitializeFolderGeneralDlg(PFOLDER_PROPERTIES_CONTEXT pContext)
+{
+    LPWSTR pFolderName;
+    WIN32_FILE_ATTRIBUTE_DATA FolderAttribute;
+    FILETIME ft;
+    SYSTEMTIME dt;
+    WCHAR szBuffer[MAX_PATH+5];
+    WCHAR szFormat[30] = {0};
+
+    static const WCHAR wFormat[] = {'%','0','2','d','/','%','0','2','d','/','%','0','4','d',' ',' ','%','0','2','d',':','%','0','2','u',0};
+
+    pFolderName = wcsrchr(pContext->szFolderPath, L'\\');
+    if (!pFolderName)
+        return;
+
+    /* set folder name */
+    SendDlgItemMessageW(pContext->hwndDlg, 14001, WM_SETTEXT, 0, (LPARAM) (pFolderName + 1));
+    /* set folder location */
+    pFolderName[0] = L'\0';
+    if (wcslen(pContext->szFolderPath) == 2)
+    {
+        /* folder is located at root */
+        WCHAR szDrive[4] = {L'C',L':',L'\\',L'\0'};
+        szDrive[0] = pContext->szFolderPath[0];
+        SendDlgItemMessageW(pContext->hwndDlg, 14007, WM_SETTEXT, 0, (LPARAM) szDrive);
+    }
+    else
+    {
+        SendDlgItemMessageW(pContext->hwndDlg, 14007, WM_SETTEXT, 0, (LPARAM) pContext->szFolderPath);
+    }
+    pFolderName[0] = L'\\';
+    /* get folder properties */
+    if (GetFileAttributesExW(pContext->szFolderPath, GetFileExInfoStandard, (LPVOID)&FolderAttribute))
+    {
+        if (FolderAttribute.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
+        {
+            /* check readonly button */
+            SendDlgItemMessage(pContext->hwndDlg, 14021, BM_SETCHECK, BST_CHECKED, 0);
+        }
+
+        if (FolderAttribute.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
+        {
+            /* check hidden button */
+            SendDlgItemMessage(pContext->hwndDlg, 14022, BM_SETCHECK, BST_CHECKED, 0);
+        }
+
+       if (FileTimeToLocalFileTime(&FolderAttribute.ftCreationTime, &ft))
+       {
+           FileTimeToSystemTime(&ft, &dt);
+           swprintf (szBuffer, wFormat, dt.wDay, dt.wMonth, dt.wYear, dt.wHour, dt.wMinute);
+           SendDlgItemMessageW(pContext->hwndDlg, 14015, WM_SETTEXT, 0, (LPARAM) szBuffer);
+       }
+    }
+    /* now enumerate enumerate contents */
+    wcscpy(szBuffer, pContext->szFolderPath);
+    CountFolderAndFiles((LPVOID)pContext);
+    wcscpy(pContext->szFolderPath, szBuffer);
+    /* set folder details */
+    LoadStringW(shell32_hInstance, IDS_FILE_FOLDER, szFormat, sizeof(szFormat)/sizeof(WCHAR));
+    szFormat[(sizeof(szFormat)/sizeof(WCHAR))-1] = L'\0';
+    swprintf(szBuffer, szFormat, pContext->cFiles, pContext->cFolder);
+    SendDlgItemMessageW(pContext->hwndDlg, 14011, WM_SETTEXT, 0, (LPARAM) szBuffer);
+
+    if (StrFormatByteSizeW(pContext->bSize.QuadPart, szBuffer, sizeof(szBuffer)/sizeof(WCHAR)))
+    {
+        /* store folder size */
+        SendDlgItemMessageW(pContext->hwndDlg, 14009, WM_SETTEXT, 0, (LPARAM) szBuffer);
+    }
+}
+
+
+INT_PTR
+CALLBACK
+FolderPropertiesGeneralDlg(
+    HWND hwndDlg,
+    UINT uMsg,
+    WPARAM wParam,
+    LPARAM lParam
+)
+{
+    LPPROPSHEETPAGEW ppsp;
+    PFOLDER_PROPERTIES_CONTEXT pContext;
+    HICON hIcon;
+    WIN32_FILE_ATTRIBUTE_DATA FolderAttribute;
+    LONG res;
+    LPPSHNOTIFY lppsn;
+    DWORD Attribute;
+
+    switch(uMsg)
+    {
+        case WM_INITDIALOG:
+            ppsp = (LPPROPSHEETPAGEW)lParam;
+            if (ppsp == NULL)
+                break;
+            hIcon = LoadIconW(shell32_hInstance, MAKEINTRESOURCEW(IDI_SHELL_FOLDER_OPEN));
+            if (hIcon)
+               SendDlgItemMessageW(hwndDlg, 14000, STM_SETICON,  (WPARAM)hIcon, 0);
+
+            pContext = SHAlloc(sizeof(FOLDER_PROPERTIES_CONTEXT));
+            if (pContext)
+            {
+                ZeroMemory(pContext, sizeof(FOLDER_PROPERTIES_CONTEXT));
+                pContext->hwndDlg = hwndDlg;
+                wcscpy(pContext->szFolderPath, (LPWSTR)ppsp->lParam);
+                SetWindowLongPtr(hwndDlg, DWL_USER, (LONG_PTR)pContext);
+                InitializeFolderGeneralDlg(pContext);
+            }
+            return TRUE;
+        case WM_COMMAND:
+            if (HIWORD(wParam) == BN_CLICKED)
+            {
+               PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
+            }
+            break;
+        case WM_DESTROY:
+            pContext = (PFOLDER_PROPERTIES_CONTEXT)GetWindowLongPtr(hwndDlg, DWL_USER);
+            SHFree((LPVOID)pContext);
+            break;
+        case WM_NOTIFY:
+            pContext = (PFOLDER_PROPERTIES_CONTEXT)GetWindowLongPtr(hwndDlg, DWL_USER);
+            lppsn = (LPPSHNOTIFY) lParam;
+            if (lppsn->hdr.code == PSN_APPLY)
+            {
+                if (GetFileAttributesExW(pContext->szFolderPath, GetFileExInfoStandard, (LPVOID)&FolderAttribute))
+                {
+                    res = SendDlgItemMessageW(hwndDlg, 14021, BM_GETCHECK, 0, 0);
+                    if (res == BST_CHECKED)
+                        FolderAttribute.dwFileAttributes |= FILE_ATTRIBUTE_READONLY;
+                    else
+                        FolderAttribute.dwFileAttributes &= (~FILE_ATTRIBUTE_READONLY);
+
+                    res = SendDlgItemMessageW(hwndDlg, 14022, BM_GETCHECK, 0, 0);
+                    if (res == BST_CHECKED)
+                        FolderAttribute.dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN;
+                    else
+                        FolderAttribute.dwFileAttributes &= (~FILE_ATTRIBUTE_HIDDEN);
+
+                    Attribute = FolderAttribute.dwFileAttributes & 
+(FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_NORMAL|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_TEMPORARY);
+
+                    SetFileAttributesW(pContext->szFolderPath, Attribute);
+                }
+                SetWindowLongPtr( hwndDlg, DWL_MSGRESULT, PSNRET_NOERROR );
+                return TRUE;
+            }
+            break;
+    }
+    return FALSE;
+}
+
+static
+BOOL
+CALLBACK
+FolderAddPropSheetPageProc(HPROPSHEETPAGE hpage, LPARAM lParam)
+{
+    PROPSHEETHEADERW *ppsh = (PROPSHEETHEADERW *)lParam;
+    if (ppsh != NULL && ppsh->nPages < MAX_PROPERTY_SHEET_PAGE)
+    {
+        ppsh->u3.phpage[ppsh->nPages++] = hpage;
+        return TRUE;
+    }
+    return FALSE;
+}
+
+BOOL
+SH_ShowFolderProperties(LPWSTR pwszFolder,  LPCITEMIDLIST pidlFolder, LPCITEMIDLIST * apidl)
+{
+    HPROPSHEETPAGE hppages[MAX_PROPERTY_SHEET_PAGE];
+    HPROPSHEETPAGE hpage;
+    PROPSHEETHEADERW psh;
+    BOOL ret;
+    WCHAR szName[MAX_PATH] = {0};
+    HPSXA hpsx = NULL;
+    LPWSTR pFolderName;
+    IDataObject * pDataObj = NULL;
+
+    if (!PathIsDirectoryW(pwszFolder))
+        return FALSE;
+
+    pFolderName = wcsrchr(pwszFolder, L'\\');
+    if (!pFolderName)
+        return FALSE;
+
+    wcscpy(szName, pFolderName + 1);
+
+    hpage = SH_CreatePropertySheetPage("SHELL_FOLDER_GENERAL_DLG", FolderPropertiesGeneralDlg, (LPARAM)pwszFolder, NULL);
+    if (!hpage)
+        return FALSE;
+
+    ZeroMemory(&psh, sizeof(PROPSHEETHEADERW));
+    hppages[psh.nPages] = hpage;
+    psh.nPages++;
+    psh.dwSize = sizeof(PROPSHEETHEADERW);
+    psh.dwFlags = PSH_PROPTITLE;
+    psh.hwndParent = NULL;
+    psh.u3.phpage = hppages;
+    psh.pszCaption = szName;
+
+
+    if (SHCreateDataObject(pidlFolder, 1, apidl, NULL, &IID_IDataObject, (void**)&pDataObj) == S_OK)
+    {
+        hpsx = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, L"Directory", MAX_PROPERTY_SHEET_PAGE-1, pDataObj);
+        if (hpsx)
+        {
+            SHAddFromPropSheetExtArray(hpsx,
+                                      (LPFNADDPROPSHEETPAGE)FolderAddPropSheetPageProc,
+                                      (LPARAM)&psh);
+        }
+    }
+
+    ret = PropertySheetW(&psh);
+   if (pDataObj)
+       IDataObject_Release(pDataObj);
+
+   if (hpsx)
+       SHDestroyPropSheetExtArray(hpsx);
+
+    if (ret < 0)
+        return FALSE;
+    else
+        return TRUE;
+}