Create the AHCI branch for Aman's work
[reactos.git] / dll / win32 / shell32 / dialogs / folder_options.cpp
1 /*
2 * Open With Context Menu extension
3 *
4 * Copyright 2007 Johannes Anderwald <johannes.anderwald@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 WINE_DEFAULT_DEBUG_CHANNEL (fprop);
24
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 WCHAR FileExtension[30];
38 WCHAR FileDescription[100];
39 WCHAR ClassKey[MAX_PATH];
40 } FOLDER_FILE_TYPE_ENTRY, *PFOLDER_FILE_TYPE_ENTRY;
41
42 typedef struct
43 {
44 LPCWSTR szKeyName;
45 UINT ResourceID;
46 } FOLDER_VIEW_ENTRY, PFOLDER_VIEW_ENTRY;
47 /*
48 static FOLDER_VIEW_ENTRY s_Options[] =
49 {
50 { L"AlwaysShowMenus", IDS_ALWAYSSHOWMENUS },
51 { L"AutoCheckSelect", -1 },
52 { L"ClassicViewState", -1 },
53 { L"DontPrettyPath", -1 },
54 { L"Filter", -1 },
55 { L"FolderContentsInfoTip", IDS_FOLDERCONTENTSTIP },
56 { L"FriendlyTree", -1 },
57 { L"Hidden", -1, },
58 { L"HideFileExt", IDS_HIDEFILEEXT },
59 { L"HideIcons", -1},
60 { L"IconsOnly", -1},
61 { L"ListviewAlphaSelect", -1},
62 { L"ListviewShadow", -1},
63 { L"ListviewWatermark", -1},
64 { L"MapNetDrvBtn", -1},
65 { L"PersistBrowsers", -1},
66 { L"SeperateProcess", IDS_SEPERATEPROCESS},
67 { L"ServerAdminUI", -1},
68 { L"SharingWizardOn", IDS_USESHAREWIZARD},
69 { L"ShowCompColor", IDS_COMPCOLOR},
70 { L"ShowInfoTip", IDS_SHOWINFOTIP},
71 { L"ShowPreviewHandlers", -1},
72 { L"ShowSuperHidden", IDS_HIDEOSFILES},
73 { L"ShowTypeOverlay", -1},
74 { L"Start_ShowMyGames", -1},
75 { L"StartMenuInit", -1},
76 { L"SuperHidden", -1},
77 { L"TypeAhead", -1},
78 { L"Webview", -1},
79 { NULL, -1}
80
81 };
82 */
83
84 EXTERN_C HPSXA WINAPI SHCreatePropSheetExtArrayEx(HKEY hKey, LPCWSTR pszSubKey, UINT max_iface, IDataObject *pDataObj);
85
86 INT_PTR
87 CALLBACK
88 FolderOptionsGeneralDlg(
89 HWND hwndDlg,
90 UINT uMsg,
91 WPARAM wParam,
92 LPARAM lParam
93 )
94 {
95 return FALSE;
96 }
97
98 static
99 VOID
100 InitializeFolderOptionsListCtrl(HWND hwndDlg)
101 {
102 RECT clientRect;
103 LVCOLUMNW col;
104 WCHAR szName[50];
105 HWND hDlgCtrl;
106
107 hDlgCtrl = GetDlgItem(hwndDlg, 14003);
108
109 if (!LoadStringW(shell32_hInstance, IDS_COLUMN_EXTENSION, szName, sizeof(szName) / sizeof(WCHAR)))
110 szName[0] = 0;
111 szName[(sizeof(szName)/sizeof(WCHAR))-1] = 0;
112
113 GetClientRect(hDlgCtrl, &clientRect);
114 ZeroMemory(&col, sizeof(LV_COLUMN));
115 col.mask = LVCF_SUBITEM | LVCF_WIDTH | LVCF_FMT;
116 col.iSubItem = 0;
117 col.pszText = szName;
118 col.fmt = LVCFMT_LEFT;
119 col.cx = (clientRect.right - clientRect.left) - GetSystemMetrics(SM_CXVSCROLL);
120 (void)SendMessageW(hDlgCtrl, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
121
122
123
124 }
125
126 INT_PTR
127 CALLBACK
128 FolderOptionsViewDlg(
129 HWND hwndDlg,
130 UINT uMsg,
131 WPARAM wParam,
132 LPARAM lParam
133 )
134 {
135 switch(uMsg)
136 {
137 case WM_INITDIALOG:
138 InitializeFolderOptionsListCtrl(hwndDlg);
139 return TRUE;
140 }
141
142 return FALSE;
143
144 }
145
146 static
147 VOID
148 InitializeFileTypesListCtrlColumns(HWND hDlgCtrl)
149 {
150 RECT clientRect;
151 LVCOLUMNW col;
152 WCHAR szName[50];
153 DWORD dwStyle;
154 int columnSize = 140;
155
156
157 if (!LoadStringW(shell32_hInstance, IDS_COLUMN_EXTENSION, szName, sizeof(szName) / sizeof(WCHAR)))
158 {
159 /* default to english */
160 wcscpy(szName, L"Extensions");
161 }
162
163 /* make sure its null terminated */
164 szName[(sizeof(szName)/sizeof(WCHAR))-1] = 0;
165
166 GetClientRect(hDlgCtrl, &clientRect);
167 ZeroMemory(&col, sizeof(LV_COLUMN));
168 columnSize = 140; //FIXME
169 col.iSubItem = 0;
170 col.mask = LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM | LVCF_FMT;
171 col.fmt = LVCFMT_FIXED_WIDTH;
172 col.cx = columnSize | LVCFMT_LEFT;
173 col.cchTextMax = wcslen(szName);
174 col.pszText = szName;
175 (void)SendMessageW(hDlgCtrl, LVM_INSERTCOLUMNW, 0, (LPARAM)&col);
176
177 if (!LoadStringW(shell32_hInstance, IDS_FILE_TYPES, szName, sizeof(szName) / sizeof(WCHAR)))
178 {
179 /* default to english */
180 wcscpy(szName, L"FileTypes");
181 }
182
183 col.iSubItem = 1;
184 col.cx = clientRect.right - clientRect.left - columnSize;
185 col.cchTextMax = wcslen(szName);
186 col.pszText = szName;
187 (void)SendMessageW(hDlgCtrl, LVM_INSERTCOLUMNW, 1, (LPARAM)&col);
188
189 /* set full select style */
190 dwStyle = (DWORD) SendMessage(hDlgCtrl, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
191 dwStyle = dwStyle | LVS_EX_FULLROWSELECT;
192 SendMessage(hDlgCtrl, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, dwStyle);
193 }
194
195 INT
196 FindItem(HWND hDlgCtrl, WCHAR * ItemName)
197 {
198 LVFINDINFOW findInfo;
199 ZeroMemory(&findInfo, sizeof(LVFINDINFOW));
200
201 findInfo.flags = LVFI_STRING;
202 findInfo.psz = ItemName;
203 return ListView_FindItem(hDlgCtrl, 0, &findInfo);
204 }
205
206 static
207 VOID
208 InsertFileType(HWND hDlgCtrl, WCHAR * szName, PINT iItem, WCHAR * szFile)
209 {
210 PFOLDER_FILE_TYPE_ENTRY Entry;
211 HKEY hKey;
212 LVITEMW lvItem;
213 DWORD dwSize;
214
215 if (szName[0] != L'.')
216 {
217 /* FIXME handle URL protocol handlers */
218 return;
219 }
220
221 /* allocate file type entry */
222 Entry = (PFOLDER_FILE_TYPE_ENTRY)HeapAlloc(GetProcessHeap(), 0, sizeof(FOLDER_FILE_TYPE_ENTRY));
223
224 if (!Entry)
225 return;
226
227 /* open key */
228 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, szName, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
229 {
230 HeapFree(GetProcessHeap(), 0, Entry);
231 return;
232 }
233
234 /* FIXME check for duplicates */
235
236 /* query for the default key */
237 dwSize = sizeof(Entry->ClassKey);
238 if (RegQueryValueExW(hKey, NULL, NULL, NULL, (LPBYTE)Entry->ClassKey, &dwSize) != ERROR_SUCCESS)
239 {
240 /* no link available */
241 Entry->ClassKey[0] = 0;
242 }
243
244 if (Entry->ClassKey[0])
245 {
246 HKEY hTemp;
247 /* try open linked key */
248 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, Entry->ClassKey, 0, KEY_READ, &hTemp) == ERROR_SUCCESS)
249 {
250 /* use linked key */
251 RegCloseKey(hKey);
252 hKey = hTemp;
253 }
254 }
255
256 /* read friendly type name */
257 if (RegLoadMUIStringW(hKey, L"FriendlyTypeName", Entry->FileDescription, sizeof(Entry->FileDescription), NULL, 0, NULL) != ERROR_SUCCESS)
258 {
259 /* read file description */
260 dwSize = sizeof(Entry->FileDescription);
261 Entry->FileDescription[0] = 0;
262
263 /* read default key */
264 RegQueryValueExW(hKey, NULL, NULL, NULL, (LPBYTE)Entry->FileDescription, &dwSize);
265 }
266
267 /* close key */
268 RegCloseKey(hKey);
269
270 /* convert extension to upper case */
271 wcscpy(Entry->FileExtension, szName);
272 _wcsupr(Entry->FileExtension);
273
274 if (!Entry->FileDescription[0])
275 {
276 /* construct default 'FileExtensionFile' by formatting the uppercase extension
277 with IDS_FILE_EXT_TYPE, outputting something like a l18n 'INI File' */
278
279 StringCchPrintf(Entry->FileDescription, _countof(Entry->FileDescription), szFile, &Entry->FileExtension[1]);
280 }
281
282 ZeroMemory(&lvItem, sizeof(LVITEMW));
283 lvItem.mask = LVIF_TEXT | LVIF_PARAM;
284 lvItem.iSubItem = 0;
285 lvItem.pszText = &Entry->FileExtension[1];
286 lvItem.iItem = *iItem;
287 lvItem.lParam = (LPARAM)Entry;
288 (void)SendMessageW(hDlgCtrl, LVM_INSERTITEMW, 0, (LPARAM)&lvItem);
289
290 ZeroMemory(&lvItem, sizeof(LVITEMW));
291 lvItem.mask = LVIF_TEXT;
292 lvItem.pszText = Entry->FileDescription;
293 lvItem.iItem = *iItem;
294 lvItem.iSubItem = 1;
295
296 (void)SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&lvItem);
297 (*iItem)++;
298 }
299
300 static
301 int
302 CALLBACK
303 ListViewCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
304 {
305 PFOLDER_FILE_TYPE_ENTRY Entry1, Entry2;
306
307 Entry1 = (PFOLDER_FILE_TYPE_ENTRY)lParam1;
308 Entry2 = (PFOLDER_FILE_TYPE_ENTRY)lParam2;
309
310 return wcsicmp(Entry1->FileExtension, Entry2->FileExtension);
311 }
312
313 static
314 BOOL
315 InitializeFileTypesListCtrl(HWND hwndDlg)
316 {
317 HWND hDlgCtrl;
318 DWORD dwIndex = 0;
319 WCHAR szName[50];
320 WCHAR szFile[100];
321 DWORD dwName;
322 LVITEMW lvItem;
323 INT iItem = 0;
324
325 hDlgCtrl = GetDlgItem(hwndDlg, 14000);
326 InitializeFileTypesListCtrlColumns(hDlgCtrl);
327
328 szFile[0] = 0;
329 if (!LoadStringW(shell32_hInstance, IDS_FILE_EXT_TYPE, szFile, _countof(szFile)))
330 {
331 /* default to english */
332 wcscpy(szFile, L"%s File");
333 }
334 szFile[(_countof(szFile))-1] = 0;
335
336 dwName = _countof(szName);
337
338 while(RegEnumKeyExW(HKEY_CLASSES_ROOT, dwIndex++, szName, &dwName, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
339 {
340 InsertFileType(hDlgCtrl, szName, &iItem, szFile);
341 dwName = _countof(szName);
342 }
343
344 /* sort list */
345 ListView_SortItems(hDlgCtrl, ListViewCompareProc, NULL);
346
347 /* select first item */
348 ZeroMemory(&lvItem, sizeof(LVITEMW));
349 lvItem.mask = LVIF_STATE;
350 lvItem.stateMask = (UINT) - 1;
351 lvItem.state = LVIS_FOCUSED | LVIS_SELECTED;
352 lvItem.iItem = 0;
353 (void)SendMessageW(hDlgCtrl, LVM_SETITEMW, 0, (LPARAM)&lvItem);
354
355 return TRUE;
356 }
357
358 static
359 PFOLDER_FILE_TYPE_ENTRY
360 FindSelectedItem(
361 HWND hDlgCtrl)
362 {
363 UINT Count, Index;
364 LVITEMW lvItem;
365
366 Count = ListView_GetItemCount(hDlgCtrl);
367
368 for (Index = 0; Index < Count; Index++)
369 {
370 ZeroMemory(&lvItem, sizeof(LVITEM));
371 lvItem.mask = LVIF_PARAM | LVIF_STATE;
372 lvItem.iItem = Index;
373 lvItem.stateMask = (UINT) - 1;
374
375 if (ListView_GetItem(hDlgCtrl, &lvItem))
376 {
377 if (lvItem.state & LVIS_SELECTED)
378 return (PFOLDER_FILE_TYPE_ENTRY)lvItem.lParam;
379 }
380 }
381
382 return NULL;
383 }
384
385 INT_PTR
386 CALLBACK
387 FolderOptionsFileTypesDlg(
388 HWND hwndDlg,
389 UINT uMsg,
390 WPARAM wParam,
391 LPARAM lParam
392 )
393 {
394 LPNMLISTVIEW lppl;
395 LVITEMW lvItem;
396 WCHAR Buffer[255], FormatBuffer[255];
397 PFOLDER_FILE_TYPE_ENTRY pItem;
398 OPENASINFO Info;
399
400 switch(uMsg)
401 {
402 case WM_INITDIALOG:
403 InitializeFileTypesListCtrl(hwndDlg);
404 return TRUE;
405 case WM_COMMAND:
406 switch(LOWORD(wParam))
407 {
408 case 14006:
409 pItem = FindSelectedItem(GetDlgItem(hwndDlg, 14000));
410 if (pItem)
411 {
412 Info.oaifInFlags = OAIF_ALLOW_REGISTRATION | OAIF_REGISTER_EXT;
413 Info.pcszClass = pItem->FileExtension;
414 SHOpenWithDialog(hwndDlg, &Info);
415 }
416 break;
417 }
418
419 break;
420 case WM_NOTIFY:
421 lppl = (LPNMLISTVIEW) lParam;
422
423 if (lppl->hdr.code == LVN_ITEMCHANGING)
424 {
425 ZeroMemory(&lvItem, sizeof(LVITEM));
426 lvItem.mask = LVIF_PARAM;
427 lvItem.iItem = lppl->iItem;
428 if (!SendMessageW(lppl->hdr.hwndFrom, LVM_GETITEMW, 0, (LPARAM)&lvItem))
429 return TRUE;
430
431 pItem = (PFOLDER_FILE_TYPE_ENTRY)lvItem.lParam;
432 if (!pItem)
433 return TRUE;
434
435 if (!(lppl->uOldState & LVIS_FOCUSED) && (lppl->uNewState & LVIS_FOCUSED))
436 {
437 /* new focused item */
438 if (!LoadStringW(shell32_hInstance, IDS_FILE_DETAILS, FormatBuffer, sizeof(FormatBuffer) / sizeof(WCHAR)))
439 {
440 /* use default english format string */
441 wcscpy(FormatBuffer, L"Details for '%s' extension");
442 }
443
444 /* format buffer */
445 swprintf(Buffer, FormatBuffer, &pItem->FileExtension[1]);
446 /* update dialog */
447 SetDlgItemTextW(hwndDlg, 14003, Buffer);
448
449 if (!LoadStringW(shell32_hInstance, IDS_FILE_DETAILSADV, FormatBuffer, sizeof(FormatBuffer) / sizeof(WCHAR)))
450 {
451 /* use default english format string */
452 wcscpy(FormatBuffer, L"Files with extension '%s' are of type '%s'. To change settings that affect all '%s' files, click Advanced.");
453 }
454 /* format buffer */
455 swprintf(Buffer, FormatBuffer, &pItem->FileExtension[1], &pItem->FileDescription[0], &pItem->FileDescription[0]);
456 /* update dialog */
457 SetDlgItemTextW(hwndDlg, 14007, Buffer);
458 }
459 }
460 break;
461 }
462
463 return FALSE;
464 }
465
466 static
467 VOID
468 ShowFolderOptionsDialog(HWND hWnd, HINSTANCE hInst)
469 {
470 PROPSHEETHEADERW pinfo;
471 HPROPSHEETPAGE hppages[3];
472 HPROPSHEETPAGE hpage;
473 UINT num_pages = 0;
474 WCHAR szOptions[100];
475
476 hpage = SH_CreatePropertySheetPage(IDD_FOLDER_OPTIONS_GENERAL, FolderOptionsGeneralDlg, 0, NULL);
477 if (hpage)
478 hppages[num_pages++] = hpage;
479
480 hpage = SH_CreatePropertySheetPage(IDD_FOLDER_OPTIONS_VIEW, FolderOptionsViewDlg, 0, NULL);
481 if (hpage)
482 hppages[num_pages++] = hpage;
483
484 hpage = SH_CreatePropertySheetPage(IDD_FOLDER_OPTIONS_FILETYPES, FolderOptionsFileTypesDlg, 0, NULL);
485 if (hpage)
486 hppages[num_pages++] = hpage;
487
488 szOptions[0] = L'\0';
489 LoadStringW(shell32_hInstance, IDS_FOLDER_OPTIONS, szOptions, sizeof(szOptions) / sizeof(WCHAR));
490 szOptions[(sizeof(szOptions)/sizeof(WCHAR))-1] = L'\0';
491
492 memset(&pinfo, 0x0, sizeof(PROPSHEETHEADERW));
493 pinfo.dwSize = sizeof(PROPSHEETHEADERW);
494 pinfo.dwFlags = PSH_NOCONTEXTHELP;
495 pinfo.nPages = num_pages;
496 pinfo.phpage = hppages;
497 pinfo.pszCaption = szOptions;
498
499 PropertySheetW(&pinfo);
500 }
501
502 static
503 VOID
504 Options_RunDLLCommon(HWND hWnd, HINSTANCE hInst, int fOptions, DWORD nCmdShow)
505 {
506 switch(fOptions)
507 {
508 case 0:
509 ShowFolderOptionsDialog(hWnd, hInst);
510 break;
511 case 1:
512 // show taskbar options dialog
513 FIXME("notify explorer to show taskbar options dialog");
514 //PostMessage(GetShellWindow(), WM_USER+22, fOptions, 0);
515 break;
516 default:
517 FIXME("unrecognized options id %d\n", fOptions);
518 }
519 }
520
521 /*************************************************************************
522 * Options_RunDLL (SHELL32.@)
523 */
524 EXTERN_C VOID WINAPI Options_RunDLL(HWND hWnd, HINSTANCE hInst, LPCSTR cmd, DWORD nCmdShow)
525 {
526 Options_RunDLLCommon(hWnd, hInst, StrToIntA(cmd), nCmdShow);
527 }
528
529 /*************************************************************************
530 * Options_RunDLLA (SHELL32.@)
531 */
532 EXTERN_C VOID WINAPI Options_RunDLLA(HWND hWnd, HINSTANCE hInst, LPCSTR cmd, DWORD nCmdShow)
533 {
534 Options_RunDLLCommon(hWnd, hInst, StrToIntA(cmd), nCmdShow);
535 }
536
537 /*************************************************************************
538 * Options_RunDLLW (SHELL32.@)
539 */
540 EXTERN_C VOID WINAPI Options_RunDLLW(HWND hWnd, HINSTANCE hInst, LPCWSTR cmd, DWORD nCmdShow)
541 {
542 Options_RunDLLCommon(hWnd, hInst, StrToIntW(cmd), nCmdShow);
543 }