[shell32]
[reactos.git] / reactos / dll / win32 / shell32 / folder_options.c
1 /*
2 * Open With Context Menu extension
3 *
4 * Copyright 2007 Johannes Anderwald <janderwald@reactos.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #include <precomp.h>
22
23
24 WINE_DEFAULT_DEBUG_CHANNEL (fprop);
25 #define MAX_PROPERTY_SHEET_PAGE (32)
26
27 /// Folder Options:
28 /// CLASSKEY = HKEY_CLASSES_ROOT\CLSID\{6DFD7C5C-2451-11d3-A299-00C04F8EF6AF}
29 /// DefaultIcon = %SystemRoot%\system32\SHELL32.dll,-210
30 /// Verbs: Open / RunAs
31 /// Cmd: rundll32.exe shell32.dll,Options_RunDLL 0
32
33 /// ShellFolder Attributes: 0x0
34
35 typedef struct
36 {
37 DWORD cFiles;
38 DWORD cFolder;
39 LARGE_INTEGER bSize;
40 HWND hwndDlg;
41 WCHAR szFolderPath[MAX_PATH];
42 }FOLDER_PROPERTIES_CONTEXT, *PFOLDER_PROPERTIES_CONTEXT;
43
44 typedef struct
45 {
46 WCHAR FileExtension[30];
47 WCHAR FileDescription[100];
48 WCHAR ClassKey[MAX_PATH];
49 }FOLDER_FILE_TYPE_ENTRY, *PFOLDER_FILE_TYPE_ENTRY;
50
51 typedef struct
52 {
53 LPCWSTR szKeyName;
54 UINT ResourceID;
55 }FOLDER_VIEW_ENTRY, PFOLDER_VIEW_ENTRY;
56 /*
57 static FOLDER_VIEW_ENTRY s_Options[] =
58 {
59 { L"AlwaysShowMenus", IDS_ALWAYSSHOWMENUS },
60 { L"AutoCheckSelect", -1 },
61 { L"ClassicViewState", -1 },
62 { L"DontPrettyPath", -1 },
63 { L"Filter", -1 },
64 { L"FolderContentsInfoTip", IDS_FOLDERCONTENTSTIP },
65 { L"FriendlyTree", -1 },
66 { L"Hidden", -1, },
67 { L"HideFileExt", IDS_HIDEFILEEXT },
68 { L"HideIcons", -1},
69 { L"IconsOnly", -1},
70 { L"ListviewAlphaSelect", -1},
71 { L"ListviewShadow", -1},
72 { L"ListviewWatermark", -1},
73 { L"MapNetDrvBtn", -1},
74 { L"PersistBrowsers", -1},
75 { L"SeperateProcess", IDS_SEPERATEPROCESS},
76 { L"ServerAdminUI", -1},
77 { L"SharingWizardOn", IDS_USESHAREWIZARD},
78 { L"ShowCompColor", IDS_COMPCOLOR},
79 { L"ShowInfoTip", IDS_SHOWINFOTIP},
80 { L"ShowPreviewHandlers", -1},
81 { L"ShowSuperHidden", IDS_HIDEOSFILES},
82 { L"ShowTypeOverlay", -1},
83 { L"Start_ShowMyGames", -1},
84 { L"StartMenuInit", -1},
85 { L"SuperHidden", -1},
86 { L"TypeAhead", -1},
87 { L"Webview", -1},
88 { NULL, -1}
89
90 };
91 */
92
93 HPSXA WINAPI SHCreatePropSheetExtArrayEx(HKEY hKey, LPCWSTR pszSubKey, UINT max_iface, IDataObject *pDataObj);
94
95 INT_PTR
96 CALLBACK
97 FolderOptionsGeneralDlg(
98 HWND hwndDlg,
99 UINT uMsg,
100 WPARAM wParam,
101 LPARAM lParam
102 )
103 {
104
105
106
107 return FALSE;
108 }
109
110 static
111 VOID
112 InitializeFolderOptionsListCtrl(HWND hwndDlg)
113 {
114 RECT clientRect;
115 LVCOLUMNW col;
116 WCHAR szName[50];
117 HWND hDlgCtrl;
118
119 hDlgCtrl = GetDlgItem(hwndDlg, 14003);
120
121 if (!LoadStringW(shell32_hInstance, IDS_COLUMN_EXTENSION, szName, sizeof(szName) / sizeof(WCHAR)))
122 szName[0] = 0;
123 szName[(sizeof(szName)/sizeof(WCHAR))-1] = 0;
124
125 GetClientRect(hDlgCtrl, &clientRect);
126 ZeroMemory(&col, sizeof(LV_COLUMN));
127 col.mask = LVCF_SUBITEM | LVCF_WIDTH | LVCF_FMT;
128 col.iSubItem = 0;
129 col.pszText = szName;
130 col.fmt = LVCFMT_LEFT;
131 col.cx = (clientRect.right - clientRect.left) - GetSystemMetrics(SM_CXVSCROLL);
132 (void)SendMessageW(hDlgCtrl, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
133
134
135
136 }
137
138
139 INT_PTR
140 CALLBACK
141 FolderOptionsViewDlg(
142 HWND hwndDlg,
143 UINT uMsg,
144 WPARAM wParam,
145 LPARAM lParam
146 )
147 {
148 switch(uMsg)
149 {
150 case WM_INITDIALOG:
151 InitializeFolderOptionsListCtrl(hwndDlg);
152 return TRUE;
153 }
154
155 return FALSE;
156
157 }
158
159 VOID
160 InitializeFileTypesListCtrlColumns(HWND hDlgCtrl)
161 {
162 RECT clientRect;
163 LVCOLUMNW col;
164 WCHAR szName[50];
165 DWORD dwStyle;
166 int columnSize = 140;
167
168
169 if (!LoadStringW(shell32_hInstance, IDS_COLUMN_EXTENSION, szName, sizeof(szName) / sizeof(WCHAR)))
170 {
171 /* default to english */
172 wcscpy(szName, L"Extensions");
173 }
174
175 /* make sure its null terminated */
176 szName[(sizeof(szName)/sizeof(WCHAR))-1] = 0;
177
178 GetClientRect(hDlgCtrl, &clientRect);
179 ZeroMemory(&col, sizeof(LV_COLUMN));
180 columnSize = 140; //FIXME
181 col.iSubItem = 0;
182 col.mask = LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM | LVCF_FMT;
183 col.fmt = LVCFMT_FIXED_WIDTH;
184 col.cx = columnSize | LVCFMT_LEFT;
185 col.cchTextMax = wcslen(szName);
186 col.pszText = szName;
187 (void)SendMessageW(hDlgCtrl, LVM_INSERTCOLUMNW, 0, (LPARAM)&col);
188
189 if (!LoadStringW(shell32_hInstance, IDS_FILE_TYPES, szName, sizeof(szName) / sizeof(WCHAR)))
190 {
191 /* default to english */
192 wcscpy(szName, L"FileTypes");
193 }
194
195 col.iSubItem = 1;
196 col.cx = clientRect.right - clientRect.left - columnSize;
197 col.cchTextMax = wcslen(szName);
198 col.pszText = szName;
199 (void)SendMessageW(hDlgCtrl, LVM_INSERTCOLUMNW, 1, (LPARAM)&col);
200
201 /* set full select style */
202 dwStyle = (DWORD) SendMessage(hDlgCtrl, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
203 dwStyle = dwStyle | LVS_EX_FULLROWSELECT;
204 SendMessage(hDlgCtrl, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, dwStyle);
205
206 }
207
208 INT
209 FindItem(HWND hDlgCtrl, WCHAR * ItemName)
210 {
211 LVFINDINFOW findInfo;
212 ZeroMemory(&findInfo, sizeof(LVFINDINFOW));
213
214 findInfo.flags = LVFI_STRING;
215 findInfo.psz = ItemName;
216 return ListView_FindItem(hDlgCtrl, 0, &findInfo);
217 }
218
219 VOID
220 InsertFileType(HWND hDlgCtrl, WCHAR * szName, PINT iItem, WCHAR * szFile)
221 {
222 PFOLDER_FILE_TYPE_ENTRY Entry;
223 HKEY hKey;
224 LVITEMW lvItem;
225 DWORD dwSize;
226
227 if (szName[0] != L'.')
228 {
229 /* FIXME handle URL protocol handlers */
230 return;
231 }
232
233 /* allocate file type entry */
234 Entry = (PFOLDER_FILE_TYPE_ENTRY)HeapAlloc(GetProcessHeap(), 0, sizeof(FOLDER_FILE_TYPE_ENTRY));
235
236 if (!Entry)
237 return;
238
239 /* open key */
240 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, szName, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
241 return;
242
243 /* FIXME check for duplicates */
244
245 /* query for the default key */
246 dwSize = sizeof(Entry->ClassKey);
247 if (RegQueryValueExW(hKey, NULL, NULL, NULL, (LPBYTE)Entry->ClassKey, &dwSize) != ERROR_SUCCESS)
248 {
249 /* no link available */
250 Entry->ClassKey[0] = 0;
251 }
252
253 if (Entry->ClassKey[0])
254 {
255 HKEY hTemp;
256 /* try open linked key */
257 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, Entry->ClassKey, 0, KEY_READ, &hTemp) == ERROR_SUCCESS)
258 {
259 /* use linked key */
260 RegCloseKey(hKey);
261 hKey = hTemp;
262 }
263 }
264
265 /* read friendly type name */
266 if (RegLoadMUIStringW(hKey, L"FriendlyTypeName", Entry->FileDescription, sizeof(Entry->FileDescription), NULL, 0, NULL) != ERROR_SUCCESS)
267 {
268 /* read file description */
269 dwSize = sizeof(Entry->FileDescription);
270 Entry->FileDescription[0] = 0;
271
272 /* read default key */
273 RegQueryValueExW(hKey, NULL, NULL, NULL, (LPBYTE)Entry->FileDescription, &dwSize);
274 }
275
276 /* close key */
277 RegCloseKey(hKey);
278
279 /* convert extension to upper case */
280 wcscpy(Entry->FileExtension, szName);
281 _wcsupr(Entry->FileExtension);
282
283 if (!Entry->FileDescription[0])
284 {
285 /* construct default 'FileExtensionFile' */
286 wcscpy(Entry->FileDescription, &Entry->FileExtension[1]);
287 wcscat(Entry->FileDescription, L" ");
288 wcscat(Entry->FileDescription, szFile);
289 }
290
291 ZeroMemory(&lvItem, sizeof(LVITEMW));
292 lvItem.mask = LVIF_TEXT | LVIF_PARAM;
293 lvItem.iSubItem = 0;
294 lvItem.pszText = &Entry->FileExtension[1];
295 lvItem.iItem = *iItem;
296 lvItem.lParam = (LPARAM)Entry;
297 (void)SendMessageW(hDlgCtrl, LVM_INSERTITEMW, 0, (LPARAM)&lvItem);
298
299 ZeroMemory(&lvItem, sizeof(LVITEMW));
300 lvItem.mask = LVIF_TEXT;
301 lvItem.pszText = Entry->FileDescription;
302 lvItem.iItem = *iItem;
303 lvItem.iSubItem = 1;
304
305 (void)SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&lvItem);
306 (*iItem)++;
307 }
308
309 int
310 CALLBACK
311 ListViewCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
312 {
313 PFOLDER_FILE_TYPE_ENTRY Entry1, Entry2;
314
315 Entry1 = (PFOLDER_FILE_TYPE_ENTRY)lParam1;
316 Entry2 = (PFOLDER_FILE_TYPE_ENTRY)lParam2;
317
318 return wcsicmp(Entry1->FileExtension, Entry2->FileExtension);
319 }
320
321 BOOL
322 InitializeFileTypesListCtrl(HWND hwndDlg)
323 {
324 HWND hDlgCtrl;
325 DWORD dwIndex = 0;
326 WCHAR szName[50];
327 WCHAR szFile[100];
328 DWORD dwName;
329 LVITEMW lvItem;
330 INT iItem = 0;
331
332 hDlgCtrl = GetDlgItem(hwndDlg, 14000);
333 InitializeFileTypesListCtrlColumns(hDlgCtrl);
334
335 szFile[0] = 0;
336 if (!LoadStringW(shell32_hInstance, IDS_SHV_COLUMN1, szFile, sizeof(szFile) / sizeof(WCHAR)))
337 {
338 /* default to english */
339 wcscpy(szFile, L"File");
340 }
341 szFile[(sizeof(szFile)/sizeof(WCHAR))-1] = 0;
342
343 dwName = sizeof(szName) / sizeof(WCHAR);
344
345 while(RegEnumKeyExW(HKEY_CLASSES_ROOT, dwIndex++, szName, &dwName, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
346 {
347 InsertFileType(hDlgCtrl, szName, &iItem, szFile);
348 dwName = sizeof(szName) / sizeof(WCHAR);
349 }
350
351 /* sort list */
352 ListView_SortItems(hDlgCtrl, ListViewCompareProc, NULL);
353
354 /* select first item */
355 ZeroMemory(&lvItem, sizeof(LVITEMW));
356 lvItem.mask = LVIF_STATE;
357 lvItem.stateMask = (UINT)-1;
358 lvItem.state = LVIS_FOCUSED|LVIS_SELECTED;
359 lvItem.iItem = 0;
360 (void)SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&lvItem);
361
362 return TRUE;
363 }
364
365 PFOLDER_FILE_TYPE_ENTRY
366 FindSelectedItem(
367 HWND hDlgCtrl)
368 {
369 UINT Count, Index;
370 LVITEMW lvItem;
371
372 Count = ListView_GetItemCount(hDlgCtrl);
373
374 for (Index = 0; Index < Count; Index++)
375 {
376 ZeroMemory(&lvItem, sizeof(LVITEM));
377 lvItem.mask = LVIF_PARAM | LVIF_STATE;
378 lvItem.iItem = Index;
379 lvItem.stateMask = (UINT)-1;
380
381 if (ListView_GetItem(hDlgCtrl, &lvItem))
382 {
383 if (lvItem.state & LVIS_SELECTED)
384 return (PFOLDER_FILE_TYPE_ENTRY)lvItem.lParam;
385 }
386 }
387
388 return NULL;
389 }
390
391
392 INT_PTR
393 CALLBACK
394 FolderOptionsFileTypesDlg(
395 HWND hwndDlg,
396 UINT uMsg,
397 WPARAM wParam,
398 LPARAM lParam)
399 {
400 LPNMLISTVIEW lppl;
401 LVITEMW lvItem;
402 WCHAR Buffer[255], FormatBuffer[255];
403 PFOLDER_FILE_TYPE_ENTRY pItem;
404 OPENASINFO Info;
405
406 switch(uMsg)
407 {
408 case WM_INITDIALOG:
409 InitializeFileTypesListCtrl(hwndDlg);
410 return TRUE;
411 case WM_COMMAND:
412 switch(LOWORD(wParam))
413 {
414 case 14006:
415 pItem = FindSelectedItem(GetDlgItem(hwndDlg, 14000));
416 if (pItem)
417 {
418 Info.oaifInFlags = OAIF_ALLOW_REGISTRATION | OAIF_REGISTER_EXT;
419 Info.pcszClass = pItem->FileExtension;
420 SHOpenWithDialog(hwndDlg, &Info);
421 }
422 break;
423 }
424
425 break;
426 case WM_NOTIFY:
427 lppl = (LPNMLISTVIEW) lParam;
428
429 if (lppl->hdr.code == LVN_ITEMCHANGING)
430 {
431 ZeroMemory(&lvItem, sizeof(LVITEM));
432 lvItem.mask = LVIF_PARAM;
433 lvItem.iItem = lppl->iItem;
434 if (!SendMessageW(lppl->hdr.hwndFrom, LVM_GETITEMW, 0, (LPARAM)&lvItem))
435 return TRUE;
436
437 pItem = (PFOLDER_FILE_TYPE_ENTRY)lvItem.lParam;
438 if (!pItem)
439 return TRUE;
440
441 if (!(lppl->uOldState & LVIS_FOCUSED) && (lppl->uNewState & LVIS_FOCUSED))
442 {
443 /* new focused item */
444 if (!LoadStringW(shell32_hInstance, IDS_FILE_DETAILS, FormatBuffer, sizeof(FormatBuffer) / sizeof(WCHAR)))
445 {
446 /* use default english format string */
447 wcscpy(FormatBuffer, L"Details for '%s' extension");
448 }
449
450 /* format buffer */
451 swprintf(Buffer, FormatBuffer, &pItem->FileExtension[1]);
452 /* update dialog */
453 SendDlgItemMessageW(hwndDlg, 14003, WM_SETTEXT, 0, (LPARAM)Buffer);
454
455 if (!LoadStringW(shell32_hInstance, IDS_FILE_DETAILSADV, FormatBuffer, sizeof(FormatBuffer) / sizeof(WCHAR)))
456 {
457 /* use default english format string */
458 wcscpy(FormatBuffer, L"Files with extension '%s' are of type '%s'. To change settings that affect all '%s' files, click Advanced.");
459 }
460 /* format buffer */
461 swprintf(Buffer, FormatBuffer, &pItem->FileExtension[1], &pItem->FileDescription[0], &pItem->FileDescription[0]);
462 /* update dialog */
463 SendDlgItemMessageW(hwndDlg, 14007, WM_SETTEXT, 0, (LPARAM)Buffer);
464 }
465 }
466 break;
467 }
468
469 return FALSE;
470 }
471
472
473 VOID
474 ShowFolderOptionsDialog(HWND hWnd, HINSTANCE hInst)
475 {
476 PROPSHEETHEADERW pinfo;
477 HPROPSHEETPAGE hppages[3];
478 HPROPSHEETPAGE hpage;
479 UINT num_pages = 0;
480 WCHAR szOptions[100];
481
482 hpage = SH_CreatePropertySheetPage("FOLDER_OPTIONS_GENERAL_DLG", FolderOptionsGeneralDlg, 0, NULL);
483 if (hpage)
484 hppages[num_pages++] = hpage;
485
486 hpage = SH_CreatePropertySheetPage("FOLDER_OPTIONS_VIEW_DLG", FolderOptionsViewDlg, 0, NULL);
487 if (hpage)
488 hppages[num_pages++] = hpage;
489
490 hpage = SH_CreatePropertySheetPage("FOLDER_OPTIONS_FILETYPES_DLG", FolderOptionsFileTypesDlg, 0, NULL);
491 if (hpage)
492 hppages[num_pages++] = hpage;
493
494 szOptions[0] = L'\0';
495 LoadStringW(shell32_hInstance, IDS_FOLDER_OPTIONS, szOptions, sizeof(szOptions) / sizeof(WCHAR));
496 szOptions[(sizeof(szOptions)/sizeof(WCHAR))-1] = L'\0';
497
498 memset(&pinfo, 0x0, sizeof(PROPSHEETHEADERW));
499 pinfo.dwSize = sizeof(PROPSHEETHEADERW);
500 pinfo.dwFlags = PSH_NOCONTEXTHELP;
501 pinfo.nPages = num_pages;
502 pinfo.u3.phpage = hppages;
503 pinfo.pszCaption = szOptions;
504
505 PropertySheetW(&pinfo);
506 }
507
508 VOID
509 Options_RunDLLCommon(HWND hWnd, HINSTANCE hInst, int fOptions, DWORD nCmdShow)
510 {
511 switch(fOptions)
512 {
513 case 0:
514 ShowFolderOptionsDialog(hWnd, hInst);
515 break;
516 case 1:
517 // show taskbar options dialog
518 FIXME("notify explorer to show taskbar options dialog");
519 //PostMessage(GetShellWindow(), WM_USER+22, fOptions, 0);
520 break;
521 default:
522 FIXME("unrecognized options id %d\n", fOptions);
523 }
524 }
525
526 /*************************************************************************
527 * Options_RunDLL (SHELL32.@)
528 */
529 VOID WINAPI Options_RunDLL(HWND hWnd, HINSTANCE hInst, LPCSTR cmd, DWORD nCmdShow)
530 {
531 Options_RunDLLCommon(hWnd, hInst, StrToIntA(cmd), nCmdShow);
532 }
533 /*************************************************************************
534 * Options_RunDLLA (SHELL32.@)
535 */
536 VOID WINAPI Options_RunDLLA(HWND hWnd, HINSTANCE hInst, LPCSTR cmd, DWORD nCmdShow)
537 {
538 Options_RunDLLCommon(hWnd, hInst, StrToIntA(cmd), nCmdShow);
539 }
540
541 /*************************************************************************
542 * Options_RunDLLW (SHELL32.@)
543 */
544 VOID WINAPI Options_RunDLLW(HWND hWnd, HINSTANCE hInst, LPCWSTR cmd, DWORD nCmdShow)
545 {
546 Options_RunDLLCommon(hWnd, hInst, StrToIntW(cmd), nCmdShow);
547 }
548
549 static
550 DWORD WINAPI
551 CountFolderAndFiles(LPVOID lParam)
552 {
553 WIN32_FIND_DATAW FindData;
554 HANDLE hFile;
555 UINT Length;
556 LPWSTR pOffset;
557 BOOL ret;
558 PFOLDER_PROPERTIES_CONTEXT pContext = (PFOLDER_PROPERTIES_CONTEXT) lParam;
559
560 pOffset = PathAddBackslashW(pContext->szFolderPath);
561 if (!pOffset)
562 return 0;
563
564 Length = pOffset - pContext->szFolderPath;
565
566 wcscpy(pOffset, L"*.*");
567 hFile = FindFirstFileW(pContext->szFolderPath, &FindData);
568 if (hFile == INVALID_HANDLE_VALUE)
569 return 0;
570
571 do
572 {
573 ret = FindNextFileW(hFile, &FindData);
574 if (ret)
575 {
576 if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
577 {
578 if (FindData.cFileName[0] == L'.' && FindData.cFileName[1] == L'.' &&
579 FindData.cFileName[2] == L'\0')
580 continue;
581
582 pContext->cFolder++;
583 wcscpy(pOffset, FindData.cFileName);
584 CountFolderAndFiles((LPVOID)pContext);
585 pOffset[0] = L'\0';
586 }
587 else
588 {
589 pContext->cFiles++;
590 pContext->bSize.u.LowPart += FindData.nFileSizeLow;
591 pContext->bSize.u.HighPart += FindData.nFileSizeHigh;
592 }
593 }
594 else if (GetLastError() == ERROR_NO_MORE_FILES)
595 {
596 break;
597 }
598 }while(1);
599
600 FindClose(hFile);
601 return 1;
602 }
603
604 static
605 VOID
606 InitializeFolderGeneralDlg(PFOLDER_PROPERTIES_CONTEXT pContext)
607 {
608 LPWSTR pFolderName;
609 WIN32_FILE_ATTRIBUTE_DATA FolderAttribute;
610 FILETIME ft;
611 SYSTEMTIME dt;
612 WCHAR szBuffer[MAX_PATH+5];
613 WCHAR szFormat[30] = {0};
614
615 static const WCHAR wFormat[] = {'%','0','2','d','/','%','0','2','d','/','%','0','4','d',' ',' ','%','0','2','d',':','%','0','2','u',0};
616
617 pFolderName = wcsrchr(pContext->szFolderPath, L'\\');
618 if (!pFolderName)
619 return;
620
621 /* set folder name */
622 SendDlgItemMessageW(pContext->hwndDlg, 14001, WM_SETTEXT, 0, (LPARAM) (pFolderName + 1));
623 /* set folder location */
624 pFolderName[0] = L'\0';
625 if (wcslen(pContext->szFolderPath) == 2)
626 {
627 /* folder is located at root */
628 WCHAR szDrive[4] = {L'C',L':',L'\\',L'\0'};
629 szDrive[0] = pContext->szFolderPath[0];
630 SendDlgItemMessageW(pContext->hwndDlg, 14007, WM_SETTEXT, 0, (LPARAM) szDrive);
631 }
632 else
633 {
634 SendDlgItemMessageW(pContext->hwndDlg, 14007, WM_SETTEXT, 0, (LPARAM) pContext->szFolderPath);
635 }
636 pFolderName[0] = L'\\';
637 /* get folder properties */
638 if (GetFileAttributesExW(pContext->szFolderPath, GetFileExInfoStandard, (LPVOID)&FolderAttribute))
639 {
640 if (FolderAttribute.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
641 {
642 /* check readonly button */
643 SendDlgItemMessage(pContext->hwndDlg, 14021, BM_SETCHECK, BST_CHECKED, 0);
644 }
645
646 if (FolderAttribute.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
647 {
648 /* check hidden button */
649 SendDlgItemMessage(pContext->hwndDlg, 14022, BM_SETCHECK, BST_CHECKED, 0);
650 }
651
652 if (FileTimeToLocalFileTime(&FolderAttribute.ftCreationTime, &ft))
653 {
654 FileTimeToSystemTime(&ft, &dt);
655 swprintf (szBuffer, wFormat, dt.wDay, dt.wMonth, dt.wYear, dt.wHour, dt.wMinute);
656 SendDlgItemMessageW(pContext->hwndDlg, 14015, WM_SETTEXT, 0, (LPARAM) szBuffer);
657 }
658 }
659 /* now enumerate enumerate contents */
660 wcscpy(szBuffer, pContext->szFolderPath);
661 CountFolderAndFiles((LPVOID)pContext);
662 wcscpy(pContext->szFolderPath, szBuffer);
663 /* set folder details */
664 LoadStringW(shell32_hInstance, IDS_FILE_FOLDER, szFormat, sizeof(szFormat)/sizeof(WCHAR));
665 szFormat[(sizeof(szFormat)/sizeof(WCHAR))-1] = L'\0';
666 swprintf(szBuffer, szFormat, pContext->cFiles, pContext->cFolder);
667 SendDlgItemMessageW(pContext->hwndDlg, 14011, WM_SETTEXT, 0, (LPARAM) szBuffer);
668
669 if (StrFormatByteSizeW(pContext->bSize.QuadPart, szBuffer, sizeof(szBuffer)/sizeof(WCHAR)))
670 {
671 /* store folder size */
672 SendDlgItemMessageW(pContext->hwndDlg, 14009, WM_SETTEXT, 0, (LPARAM) szBuffer);
673 }
674 }
675
676
677 INT_PTR
678 CALLBACK
679 FolderPropertiesGeneralDlg(
680 HWND hwndDlg,
681 UINT uMsg,
682 WPARAM wParam,
683 LPARAM lParam
684 )
685 {
686 LPPROPSHEETPAGEW ppsp;
687 PFOLDER_PROPERTIES_CONTEXT pContext;
688 HICON hIcon;
689 WIN32_FILE_ATTRIBUTE_DATA FolderAttribute;
690 LONG res;
691 LPPSHNOTIFY lppsn;
692 DWORD Attribute;
693
694 switch(uMsg)
695 {
696 case WM_INITDIALOG:
697 ppsp = (LPPROPSHEETPAGEW)lParam;
698 if (ppsp == NULL)
699 break;
700 hIcon = LoadIconW(shell32_hInstance, MAKEINTRESOURCEW(IDI_SHELL_FOLDER_OPEN));
701 if (hIcon)
702 SendDlgItemMessageW(hwndDlg, 14000, STM_SETICON, (WPARAM)hIcon, 0);
703
704 pContext = SHAlloc(sizeof(FOLDER_PROPERTIES_CONTEXT));
705 if (pContext)
706 {
707 ZeroMemory(pContext, sizeof(FOLDER_PROPERTIES_CONTEXT));
708 pContext->hwndDlg = hwndDlg;
709 wcscpy(pContext->szFolderPath, (LPWSTR)ppsp->lParam);
710 SetWindowLongPtr(hwndDlg, DWL_USER, (LONG_PTR)pContext);
711 InitializeFolderGeneralDlg(pContext);
712 }
713 return TRUE;
714 case WM_COMMAND:
715 if (HIWORD(wParam) == BN_CLICKED)
716 {
717 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
718 }
719 break;
720 case WM_DESTROY:
721 pContext = (PFOLDER_PROPERTIES_CONTEXT)GetWindowLongPtr(hwndDlg, DWL_USER);
722 SHFree((LPVOID)pContext);
723 break;
724 case WM_NOTIFY:
725 pContext = (PFOLDER_PROPERTIES_CONTEXT)GetWindowLongPtr(hwndDlg, DWL_USER);
726 lppsn = (LPPSHNOTIFY) lParam;
727 if (lppsn->hdr.code == PSN_APPLY)
728 {
729 if (GetFileAttributesExW(pContext->szFolderPath, GetFileExInfoStandard, (LPVOID)&FolderAttribute))
730 {
731 res = SendDlgItemMessageW(hwndDlg, 14021, BM_GETCHECK, 0, 0);
732 if (res == BST_CHECKED)
733 FolderAttribute.dwFileAttributes |= FILE_ATTRIBUTE_READONLY;
734 else
735 FolderAttribute.dwFileAttributes &= (~FILE_ATTRIBUTE_READONLY);
736
737 res = SendDlgItemMessageW(hwndDlg, 14022, BM_GETCHECK, 0, 0);
738 if (res == BST_CHECKED)
739 FolderAttribute.dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN;
740 else
741 FolderAttribute.dwFileAttributes &= (~FILE_ATTRIBUTE_HIDDEN);
742
743 Attribute = FolderAttribute.dwFileAttributes &
744 (FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_NORMAL|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_TEMPORARY);
745
746 SetFileAttributesW(pContext->szFolderPath, Attribute);
747 }
748 SetWindowLongPtr( hwndDlg, DWL_MSGRESULT, PSNRET_NOERROR );
749 return TRUE;
750 }
751 break;
752 }
753 return FALSE;
754 }
755
756 static
757 BOOL
758 CALLBACK
759 FolderAddPropSheetPageProc(HPROPSHEETPAGE hpage, LPARAM lParam)
760 {
761 PROPSHEETHEADERW *ppsh = (PROPSHEETHEADERW *)lParam;
762 if (ppsh != NULL && ppsh->nPages < MAX_PROPERTY_SHEET_PAGE)
763 {
764 ppsh->u3.phpage[ppsh->nPages++] = hpage;
765 return TRUE;
766 }
767 return FALSE;
768 }
769
770 BOOL
771 SH_ShowFolderProperties(LPWSTR pwszFolder, LPCITEMIDLIST pidlFolder, LPCITEMIDLIST * apidl)
772 {
773 HPROPSHEETPAGE hppages[MAX_PROPERTY_SHEET_PAGE];
774 HPROPSHEETPAGE hpage;
775 PROPSHEETHEADERW psh;
776 BOOL ret;
777 WCHAR szName[MAX_PATH] = {0};
778 HPSXA hpsx = NULL;
779 LPWSTR pFolderName;
780 IDataObject * pDataObj = NULL;
781
782 if (!PathIsDirectoryW(pwszFolder))
783 return FALSE;
784
785 pFolderName = wcsrchr(pwszFolder, L'\\');
786 if (!pFolderName)
787 return FALSE;
788
789 wcscpy(szName, pFolderName + 1);
790
791 hpage = SH_CreatePropertySheetPage("SHELL_FOLDER_GENERAL_DLG", FolderPropertiesGeneralDlg, (LPARAM)pwszFolder, NULL);
792 if (!hpage)
793 return FALSE;
794
795 ZeroMemory(&psh, sizeof(PROPSHEETHEADERW));
796 hppages[psh.nPages] = hpage;
797 psh.nPages++;
798 psh.dwSize = sizeof(PROPSHEETHEADERW);
799 psh.dwFlags = PSH_PROPTITLE;
800 psh.hwndParent = NULL;
801 psh.u3.phpage = hppages;
802 psh.pszCaption = szName;
803
804
805 if (SHCreateDataObject(pidlFolder, 1, apidl, NULL, &IID_IDataObject, (void**)&pDataObj) == S_OK)
806 {
807 hpsx = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, L"Directory", MAX_PROPERTY_SHEET_PAGE-1, pDataObj);
808 if (hpsx)
809 {
810 SHAddFromPropSheetExtArray(hpsx,
811 (LPFNADDPROPSHEETPAGE)FolderAddPropSheetPageProc,
812 (LPARAM)&psh);
813 }
814 }
815
816 ret = PropertySheetW(&psh);
817 if (pDataObj)
818 IDataObject_Release(pDataObj);
819
820 if (hpsx)
821 SHDestroyPropSheetExtArray(hpsx);
822
823 if (ret < 0)
824 return FALSE;
825 else
826 return TRUE;
827 }
828
829