Synced dbghelp.dll with Wine HEAD.
[reactos.git] / reactos / dll / win32 / shell32 / fprop.c
1 /*
2 * Shell Library Functions
3 *
4 * Copyright 2005 Johannes Anderwald
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #define COBJMACROS
22 #define NONAMELESSUNION
23
24 #include "config.h"
25 #include "wine/port.h"
26 #include <string.h>
27 #include <stdarg.h>
28 #include <stdio.h>
29 #include "winerror.h"
30 #include "windef.h"
31 #include "winbase.h"
32 #include "winreg.h"
33 #include "wingdi.h"
34 #include "winuser.h"
35 #include "commdlg.h"
36 #include "wine/debug.h"
37
38 #include "shellapi.h"
39 #include <shlwapi.h>
40 #include "shlobj.h"
41 #include "shell32_main.h"
42 #include "shresdef.h"
43 #include "undocshell.h"
44 #include "prsht.h"
45
46 WINE_DEFAULT_DEBUG_CHANNEL(shell);
47
48 #define MAX_PROPERTY_SHEET_PAGE 32
49
50 typedef struct _LANGANDCODEPAGE_
51 {
52 WORD lang;
53 WORD code;
54 } LANGANDCODEPAGE, *LPLANGANDCODEPAGE;
55
56 HPSXA WINAPI SHCreatePropSheetExtArrayEx(HKEY hKey, LPCWSTR pszSubKey, UINT max_iface, IDataObject *pDataObj);
57 /*************************************************************************
58 *
59 * SH_CreatePropertySheetPage [Internal]
60 *
61 * creates a property sheet page from an resource name
62 *
63 */
64 HPROPSHEETPAGE
65 SH_CreatePropertySheetPage(LPSTR resname, DLGPROC dlgproc, LPARAM lParam, LPWSTR szTitle)
66 {
67 HRSRC hRes;
68 LPVOID lpsztemplate;
69 PROPSHEETPAGEW ppage;
70
71 if (resname == NULL)
72 return (HPROPSHEETPAGE)0;
73
74 hRes = FindResourceA(shell32_hInstance, resname, (LPSTR)RT_DIALOG);
75
76 if (hRes == NULL)
77 {
78 ERR("failed to find resource name\n");
79 return (HPROPSHEETPAGE)0;
80 }
81 lpsztemplate = LoadResource(shell32_hInstance, hRes);
82 if (lpsztemplate == NULL)
83 return (HPROPSHEETPAGE)0;
84
85 memset(&ppage, 0x0, sizeof(PROPSHEETPAGEW));
86 ppage.dwSize = sizeof(PROPSHEETPAGEW);
87 ppage.dwFlags = PSP_DLGINDIRECT;
88 ppage.u.pResource = lpsztemplate;
89 ppage.pfnDlgProc = dlgproc;
90 ppage.lParam = lParam;
91 ppage.pszTitle = szTitle;
92 if (szTitle)
93 {
94 ppage.dwFlags |= PSP_USETITLE;
95 }
96 return CreatePropertySheetPageW(&ppage);
97 }
98
99
100
101
102
103
104
105 /*************************************************************************
106 *
107 * SH_FileGeneralFileType [Internal]
108 *
109 * retrieves file extension description from registry and sets it in dialog
110 *
111 * TODO: retrieve file extension default icon and load it
112 * find executable name from registry, retrieve description from executable
113 */
114
115 BOOL
116 SH_FileGeneralSetFileType(HWND hwndDlg, WCHAR * filext)
117 {
118 WCHAR name[MAX_PATH];
119 WCHAR value[MAX_PATH];
120 DWORD lname = MAX_PATH;
121 DWORD lvalue = MAX_PATH;
122
123 HKEY hKey;
124 LONG result;
125 HWND hDlgCtrl;
126
127 TRACE("fileext %s\n", debugstr_w(filext));
128
129 if (filext == NULL)
130 return FALSE;
131
132 hDlgCtrl = GetDlgItem(hwndDlg, 14005);
133
134 if (hDlgCtrl == NULL)
135 return FALSE;
136
137 if (RegOpenKeyW(HKEY_CLASSES_ROOT, filext, &hKey) != ERROR_SUCCESS)
138 {
139 /* the fileextension is unknown, so default to string "FileExtension File" */
140 SendMessageW(hDlgCtrl, WM_GETTEXT, (WPARAM)MAX_PATH, (LPARAM)value);
141 sprintfW(name, value, &filext[1]);
142 SendMessageW(hDlgCtrl, WM_SETTEXT, (WPARAM)NULL, (LPARAM)name);
143 return TRUE;
144 }
145 result = RegEnumValueW(hKey, 0, name, &lname, NULL, NULL, (LPBYTE)value, &lvalue);
146 RegCloseKey(hKey);
147
148 if (result != ERROR_SUCCESS)
149 return FALSE;
150 if (RegOpenKeyW(HKEY_CLASSES_ROOT, value, &hKey) == ERROR_SUCCESS)
151 {
152 if (RegLoadMUIStringW(hKey, L"FriendlyTypeName", value, MAX_PATH, NULL, 0, NULL) != ERROR_SUCCESS)
153 {
154 lvalue = lname = MAX_PATH;
155 result = RegEnumValueW(hKey,0, name, &lname, NULL, NULL, (LPBYTE)value, &lvalue);
156 }
157 lname = MAX_PATH;
158 if (RegGetValueW(hKey, L"DefaultIcon", NULL, RRF_RT_REG_SZ, NULL, name, &lname) == ERROR_SUCCESS)
159 {
160 UINT IconIndex;
161 WCHAR szBuffer[MAX_PATH];
162 WCHAR * Offset;
163 HICON hIcon = 0;
164 HRSRC hResource;
165 LPVOID pResource = NULL;
166 HGLOBAL hGlobal;
167 HANDLE hLibrary;
168 Offset = wcsrchr(name, L',');
169 if (Offset)
170 {
171 IconIndex = _wtoi(Offset + 2);
172 *Offset = L'\0';
173 name[MAX_PATH-1] = L'\0';
174 if (ExpandEnvironmentStringsW(name, szBuffer, MAX_PATH))
175 {
176 szBuffer[MAX_PATH-1] = L'\0';
177 hLibrary = LoadLibraryExW(szBuffer, NULL, LOAD_LIBRARY_AS_DATAFILE);
178 if (hLibrary)
179 {
180 hResource = FindResourceW(hLibrary, MAKEINTRESOURCEW(IconIndex), (LPCWSTR)RT_ICON);
181 if (hResource)
182 {
183 hGlobal = LoadResource(shell32_hInstance, hResource);
184 if (hGlobal)
185 {
186 pResource = LockResource(hGlobal);
187 if (pResource != NULL)
188 {
189 hIcon = CreateIconFromResource(pResource, SizeofResource(shell32_hInstance, hResource), TRUE, 0x00030000);
190 TRACE("hIcon %p,- szBuffer %s IconIndex %u error %u icon %p hResource %p pResource %p\n", hIcon, debugstr_w(szBuffer), IconIndex, MAKEINTRESOURCEW(IconIndex), hResource, pResource);
191 SendDlgItemMessageW(hwndDlg, 14000, STM_SETICON, (WPARAM)hIcon, 0);
192 }
193 }
194 }
195 FreeLibrary(hLibrary);
196 }
197 }
198 }
199 }
200 RegCloseKey(hKey);
201 }
202
203 /* file extension type */
204 value[MAX_PATH-1] = L'\0';
205 SendMessageW(hDlgCtrl, WM_SETTEXT, (WPARAM)NULL, (LPARAM)value);
206 return TRUE;
207 }
208 /*************************************************************************
209 *
210 * SHFileGeneralGetFileTimeString [Internal]
211 *
212 * formats a given LPFILETIME struct into readable user format
213 */
214
215 BOOL
216 SHFileGeneralGetFileTimeString(LPFILETIME lpFileTime, WCHAR * lpResult)
217 {
218 FILETIME ft;
219 SYSTEMTIME dt;
220 WORD wYear;
221 static const WCHAR wFormat[] = {'%','0','2','d','/','%','0','2','d','/','%','0','4','d',' ',' ','%','0','2','d',':','%','0','2','u',0};
222
223 if (lpFileTime == NULL || lpResult == NULL)
224 return FALSE;
225
226 if (!FileTimeToLocalFileTime(lpFileTime, &ft))
227 return FALSE;
228
229 FileTimeToSystemTime(&ft, &dt);
230
231 wYear = dt.wYear;
232 /* ddmmyy */
233 sprintfW (lpResult, wFormat, dt.wDay, dt.wMonth, wYear, dt.wHour, dt.wMinute);
234
235 TRACE("result %s\n",debugstr_w(lpResult));
236 return TRUE;
237 }
238
239 /*************************************************************************
240 *
241 * SH_FileGeneralSetText [Internal]
242 *
243 * sets file path string and filename string
244 *
245 */
246
247 BOOL
248 SH_FileGeneralSetText(HWND hwndDlg, WCHAR * lpstr)
249 {
250 int flength;
251 int plength;
252 WCHAR * lpdir;
253 WCHAR buff[MAX_PATH];
254 HWND hDlgCtrl;
255
256 if (lpstr == NULL)
257 return FALSE;
258
259 lpdir = strrchrW(lpstr, '\\'); /* find the last occurence of '\\' */
260
261 plength = strlenW(lpstr);
262 flength = strlenW(lpdir);
263
264 if (lpdir)
265 {
266 /* location text field */
267 strncpyW(buff, lpstr, plength - flength);
268 buff[plength - flength] = UNICODE_NULL;
269 hDlgCtrl = GetDlgItem(hwndDlg, 14009);
270 SendMessageW(hDlgCtrl, WM_SETTEXT, (WPARAM)NULL, (LPARAM)buff);
271 }
272
273 if(flength > 1)
274 {
275 /* text filename field */
276 strncpyW(buff, &lpdir[1], flength);
277 hDlgCtrl = GetDlgItem(hwndDlg, 14001);
278 SendMessageW(hDlgCtrl, WM_SETTEXT, (WPARAM)NULL, (LPARAM)buff);
279 }
280
281 return TRUE;
282 }
283
284 /*************************************************************************
285 *
286 * SH_FileGeneralSetFileSizeTime [Internal]
287 *
288 * retrieves file information from file and sets in dialog
289 *
290 */
291
292 BOOL
293 SH_FileGeneralSetFileSizeTime(HWND hwndDlg, WCHAR * lpfilename, PULARGE_INTEGER lpfilesize)
294 {
295 BOOL result;
296 HANDLE hFile;
297 FILETIME create_time;
298 FILETIME accessed_time;
299 FILETIME write_time;
300 WCHAR resultstr[MAX_PATH];
301 HWND hDlgCtrl;
302 LARGE_INTEGER file_size;
303
304 if (lpfilename == NULL)
305 return FALSE;
306
307 hFile = CreateFileW(lpfilename,
308 GENERIC_READ,
309 FILE_SHARE_READ,NULL,
310 OPEN_EXISTING,
311 FILE_ATTRIBUTE_NORMAL,
312 NULL);
313
314 if (hFile == INVALID_HANDLE_VALUE)
315 {
316 WARN("failed to open file %s\n", debugstr_w(lpfilename));
317 return FALSE;
318 }
319
320 result = GetFileTime(hFile, &create_time, &accessed_time, &write_time);
321
322 if (!result)
323 {
324 WARN("GetFileTime failed\n");
325 return FALSE;
326 }
327 if (SHFileGeneralGetFileTimeString(&create_time,resultstr))
328 {
329 hDlgCtrl = GetDlgItem(hwndDlg, 14015);
330 SendMessageW(hDlgCtrl, WM_SETTEXT, (WPARAM)NULL, (LPARAM)resultstr);
331 }
332
333 if (SHFileGeneralGetFileTimeString(&accessed_time, resultstr))
334 {
335 hDlgCtrl = GetDlgItem(hwndDlg, 14017);
336 SendMessageW(hDlgCtrl, WM_SETTEXT, (WPARAM)NULL, (LPARAM)resultstr);
337 }
338
339 if (SHFileGeneralGetFileTimeString(&write_time, resultstr))
340 {
341 hDlgCtrl = GetDlgItem(hwndDlg, 14019);
342 SendMessageW(hDlgCtrl, WM_SETTEXT, (WPARAM)NULL, (LPARAM)resultstr);
343 }
344
345 if (!GetFileSizeEx(hFile, &file_size))
346 {
347 WARN("GetFileSize failed\n");
348 CloseHandle(hFile);
349 return FALSE;
350 }
351 CloseHandle(hFile);
352 if (!StrFormatByteSizeW(file_size.QuadPart, resultstr, sizeof(resultstr)/sizeof(resultstr[0])));
353 return FALSE;
354 hDlgCtrl = GetDlgItem(hwndDlg, 14011);
355 ERR("result size %u resultstr %s %s\n", file_size.QuadPart, debugstr_w(resultstr), resultstr);
356 SendMessageW(hDlgCtrl, WM_SETTEXT, (WPARAM)NULL, (LPARAM)resultstr);
357
358 if (lpfilesize)
359 lpfilesize->QuadPart = (ULONGLONG)file_size.QuadPart;
360
361 return TRUE;
362 }
363
364 /*************************************************************************
365 *
366 * SH_SetFileVersionText [Internal]
367 *
368 *
369 */
370
371 BOOL
372 SH_FileVersionQuerySetText(HWND hwndDlg, DWORD dlgId, LPVOID pInfo, WCHAR * text, WCHAR ** resptr)
373 {
374 UINT reslen;
375 HWND hDlgCtrl;
376
377 if(hwndDlg == NULL || resptr == NULL || text == NULL)
378 return FALSE;
379
380 if(VerQueryValueW(pInfo, text, (LPVOID *)resptr, &reslen))
381 {
382 /* file description property */
383 hDlgCtrl = GetDlgItem(hwndDlg, dlgId);
384 TRACE("%s :: %s\n",debugstr_w(text), debugstr_w(*resptr));
385 SendMessageW(hDlgCtrl, WM_SETTEXT, (WPARAM)0, (LPARAM)*resptr);
386 return TRUE;
387 }
388 return FALSE;
389 }
390
391 /*************************************************************************
392 *
393 * SH_FileVersionQuerySetListText [Internal]
394 *
395 * retrieves a version string and adds it to listbox
396 *
397 */
398
399
400 BOOL
401 SH_FileVersionQuerySetListText(HWND hwndDlg, LPVOID pInfo, const WCHAR * text, WCHAR **resptr, WORD lang, WORD code)
402 {
403 UINT reslen;
404 HWND hDlgCtrl;
405 UINT index;
406 static const WCHAR wFormat[] = { '\\','S','t','r','i','n','g','F','i','l','e','I','n',
407 'f','o','\\','%','0','4','x','%','0','4','x','\\','%','s',0 };
408 WCHAR buff[256];
409
410 TRACE("text %s, resptr %p hwndDlg %p\n",debugstr_w(text), resptr, hwndDlg);
411
412 if(hwndDlg == NULL || resptr == NULL || text == NULL)
413 return FALSE;
414
415 sprintfW(buff, wFormat, lang, code, text);
416 if(VerQueryValueW(pInfo, buff, (LPVOID *)resptr, &reslen))
417 {
418 /* listbox name property */
419 hDlgCtrl = GetDlgItem(hwndDlg, 14009);
420 TRACE("%s :: %s\n",debugstr_w(text), debugstr_w(*resptr));
421 index = SendMessageW(hDlgCtrl, LB_ADDSTRING, (WPARAM)-1, (LPARAM)text);
422 SendMessageW(hDlgCtrl, LB_SETITEMDATA, (WPARAM)index, (LPARAM)(WCHAR*)*resptr);
423 return TRUE;
424 }
425 return FALSE;
426 }
427
428 /*************************************************************************
429 *
430 * SH_FileVersionInitialize [Internal]
431 *
432 * sets all file version properties in dialog
433 */
434 BOOL
435 SH_FileVersionInitialize(HWND hwndDlg, WCHAR * lpfilename)
436 {
437 LPVOID pBuf;
438 DWORD versize;
439 DWORD handle;
440 LPVOID info = NULL;
441 UINT infolen;
442 WCHAR buff[256];
443 HWND hDlgCtrl;
444 WORD lang = 0;
445 WORD code = 0;
446 LPLANGANDCODEPAGE lplangcode;
447 WCHAR * str;
448 static const WCHAR wVersionFormat[] = { '%','d','.','%','d','.','%','d','.','%','d',0 };
449 static const WCHAR wFileDescriptionFormat[] = { '\\','S','t','r','i','n','g','F','i','l','e','I','n','f','o',
450 '\\','%','0','4','x','%','0','4','x','\\','F','i','l','e','D','e','s','c','r','i','p','t','i','o','n',0 };
451 static const WCHAR wLegalCopyrightFormat[] = { '\\','S','t','r','i','n','g','F','i','l','e','I','n','f','o',
452 '\\','%','0','4','x','%','0','4','x','\\','L','e','g','a','l','C','o','p','y','r','i','g','h','t',0 };
453 static const WCHAR wTranslation[] = { 'V','a','r','F','i','l','e','I','n','f','o','\\','T','r','a','n','s','l','a','t','i','o','n',0 };
454 static const WCHAR wCompanyName[] = { 'C','o','m','p','a','n','y','N','a','m','e',0 };
455 static const WCHAR wFileVersion[] = { 'F','i','l','e','V','e','r','s','i','o','n',0 };
456 static const WCHAR wInternalName[] = { 'I','n','t','e','r','n','a','l','N','a','m','e',0 };
457 static const WCHAR wOriginalFilename[] = { 'O','r','i','g','i','n','a','l','F','i','l','e','n','a','m','e',0 };
458 static const WCHAR wProductName[] = { 'P','r','o','d','u','c','t','N','a','m','e',0 };
459 static const WCHAR wProductVersion[] = { 'P','r','o','d','u','c','t','V','e','r','s','i','o','n',0 };
460 static const WCHAR wSlash[] = { '\\',0 };
461
462
463 if(lpfilename == 0)
464 return FALSE;
465
466 if(!(versize = GetFileVersionInfoSizeW(lpfilename, &handle)))
467 {
468 WARN("GetFileVersionInfoSize failed\n");
469 return FALSE;
470 }
471
472 if(!(pBuf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, versize)))
473 {
474 WARN("HeapAlloc failed bytes %x\n",versize);
475 return FALSE;
476 }
477
478 if(!GetFileVersionInfoW(lpfilename, handle, versize, pBuf))
479 {
480 HeapFree(GetProcessHeap(), 0, pBuf);
481 return FALSE;
482 }
483 if(VerQueryValueW(pBuf, wSlash, &info, &infolen))
484 {
485 VS_FIXEDFILEINFO * inf = (VS_FIXEDFILEINFO *)info;
486 sprintfW(buff, wVersionFormat, HIWORD(inf->dwFileVersionMS),
487 LOWORD(inf->dwFileVersionMS),
488 HIWORD(inf->dwFileVersionLS),
489 LOWORD(inf->dwFileVersionLS));
490
491 hDlgCtrl = GetDlgItem(hwndDlg, 14001);
492 TRACE("MS %x LS %x res %s \n",inf->dwFileVersionMS, inf->dwFileVersionLS, debugstr_w(buff));
493 SendMessageW(hDlgCtrl, WM_SETTEXT, (WPARAM)NULL, (LPARAM)buff);
494 }
495 if(VerQueryValueW(pBuf, wTranslation, (LPVOID *)&lplangcode, &infolen))
496 {
497 /* FIXME find language from current locale / if not available,
498 * default to english
499 * for now default to first available language
500 */
501 lang = lplangcode->lang;
502 code = lplangcode->code;
503 }
504
505 sprintfW(buff, wFileDescriptionFormat, lang, code);
506 SH_FileVersionQuerySetText(hwndDlg, 14003, pBuf, buff, &str);
507
508 sprintfW(buff, wLegalCopyrightFormat, lang, code);
509 SH_FileVersionQuerySetText(hwndDlg, 14005, pBuf, buff, &str);
510
511 /* listbox properties */
512 SH_FileVersionQuerySetListText(hwndDlg, pBuf, wCompanyName, &str, lang, code);
513 SH_FileVersionQuerySetListText(hwndDlg, pBuf, wFileVersion, &str, lang, code);
514 SH_FileVersionQuerySetListText(hwndDlg, pBuf, wInternalName, &str, lang, code);
515
516 /* FIXME insert language identifier */
517
518 SH_FileVersionQuerySetListText(hwndDlg, pBuf, wOriginalFilename, &str, lang, code);
519 SH_FileVersionQuerySetListText(hwndDlg, pBuf, wProductName, &str, lang, code);
520 SH_FileVersionQuerySetListText(hwndDlg, pBuf, wProductVersion, &str, lang, code);
521 SetWindowLong(hwndDlg, DWL_USER, (LONG)pBuf);
522
523 /* select first item */
524 hDlgCtrl = GetDlgItem(hwndDlg, 14009);
525 SendMessageW(hDlgCtrl, LB_SETCURSEL, 0, 0);
526 str = (WCHAR *)SendMessageW(hDlgCtrl, LB_GETITEMDATA, (WPARAM)0, (LPARAM)NULL);
527 hDlgCtrl = GetDlgItem(hwndDlg, 14010);
528 SendMessageW(hDlgCtrl, WM_SETTEXT, (WPARAM)NULL, (LPARAM)str);
529 return TRUE;
530 }
531
532 /*************************************************************************
533 *
534 * SH_FileVersionDlgProc
535 *
536 * wnd proc of 'Version' property sheet page
537 */
538 INT_PTR
539 CALLBACK
540 SH_FileVersionDlgProc(
541 HWND hwndDlg,
542 UINT uMsg,
543 WPARAM wParam,
544 LPARAM lParam
545 )
546 {
547 LPPROPSHEETPAGE ppsp;
548 WCHAR * lpstr;
549 LPVOID * buf;
550 switch(uMsg)
551 {
552 case WM_INITDIALOG:
553 ppsp = (LPPROPSHEETPAGE)lParam;
554 if(ppsp == NULL)
555 break;
556
557 TRACE("WM_INITDIALOG hwnd %p lParam %p ppsplParam %x\n",hwndDlg, lParam, ppsp->lParam);
558
559 lpstr = (WCHAR *)ppsp->lParam;
560
561 if(lpstr == NULL)
562 break;
563
564 return SH_FileVersionInitialize(hwndDlg, lpstr);
565
566
567 case WM_COMMAND:
568 if(LOWORD(wParam) == 14009 && HIWORD(wParam) == LBN_DBLCLK)
569 {
570 HWND hDlgCtrl;
571 LRESULT lresult;
572 WCHAR * str;
573
574 hDlgCtrl = GetDlgItem(hwndDlg, 14009);
575 lresult = SendMessageW(hDlgCtrl, LB_GETCURSEL, (WPARAM)NULL, (LPARAM)NULL);
576 if(lresult == LB_ERR)
577 {
578 break;
579 }
580 str = (WCHAR *)SendMessageW(hDlgCtrl, LB_GETITEMDATA, (WPARAM)lresult, (LPARAM)NULL);
581
582 if(str == NULL)
583 {
584 break;
585 }
586 hDlgCtrl = GetDlgItem(hwndDlg, 14010);
587 TRACE("hDlgCtrl %x string %s \n",hDlgCtrl, debugstr_w(str));
588 SendMessageW(hDlgCtrl, WM_SETTEXT, (WPARAM)NULL, (LPARAM)str);
589 return TRUE;
590 }
591 break;
592
593 case WM_DESTROY:
594 buf = (LPVOID)GetWindowLong(hwndDlg, DWL_USER);
595 HeapFree(GetProcessHeap(), 0, buf);
596 break;
597
598 default:
599 break;
600 }
601 return FALSE;
602 }
603
604 /*************************************************************************
605 *
606 * SH_FileGeneralDlgProc
607 *
608 * wnd proc of 'General' property sheet page
609 *
610 */
611
612 INT_PTR
613 CALLBACK
614 SH_FileGeneralDlgProc(
615 HWND hwndDlg,
616 UINT uMsg,
617 WPARAM wParam,
618 LPARAM lParam
619 )
620 {
621 LPPROPSHEETPAGEW ppsp;
622 WCHAR * lpstr;
623 switch(uMsg)
624 {
625 case WM_INITDIALOG:
626 ppsp = (LPPROPSHEETPAGEW)lParam;
627 if (ppsp == NULL)
628 break;
629 TRACE("WM_INITDIALOG hwnd %p lParam %p ppsplParam %S\n",hwndDlg, lParam, ppsp->lParam);
630
631 lpstr = (WCHAR *)ppsp->lParam;
632
633 if ( lpstr == NULL)
634 {
635 ERR("no filename\n");
636 break;
637 }
638 /* set general text properties filename filelocation and icon */
639 SH_FileGeneralSetText(hwndDlg, lpstr);
640 /* enumerate file extension from registry and application which opens it*/
641 SH_FileGeneralSetFileType(hwndDlg, strrchrW(lpstr, '.'));
642 /* set file time create/modfied/accessed */
643 SH_FileGeneralSetFileSizeTime(hwndDlg, lpstr, NULL);
644 return TRUE;
645 default:
646 break;
647 }
648 return FALSE;
649 }
650
651 BOOL CALLBACK AddShellPropSheetExCallback(HPROPSHEETPAGE hPage, LPARAM lParam)
652 {
653 UINT iIndex;
654 HPROPSHEETPAGE * hppages = (HPROPSHEETPAGE *)lParam;
655
656 TRACE("AddShellPropSheetExCallback called\n");
657 for(iIndex = 0; iIndex < MAX_PROPERTY_SHEET_PAGE; iIndex++)
658 {
659 if (hppages[iIndex] == NULL)
660 {
661 hppages[iIndex] = hPage;
662 return TRUE;
663 }
664 }
665 return FALSE;
666 }
667
668
669 int
670 EnumPropSheetExt(LPWSTR wFileName, HPROPSHEETPAGE * hppages, int NumPages, HPSXA * hpsxa, IDataObject *pDataObj)
671 {
672 WCHAR szName[100];
673 WCHAR * pOffset;
674 UINT Length;
675 DWORD dwName;
676 int Pages;
677 CLSID clsid;
678
679 pOffset = wcsrchr(wFileName, L'.');
680 if (!pOffset)
681 {
682 Length = wcslen(szName);
683 if (Length >=94)
684 return 0;
685
686 if (CLSIDFromString(wFileName, &clsid) == NOERROR)
687 {
688 wcscpy(szName, L"CLSID\\");
689 wcscpy(&szName[6], wFileName);
690 }
691 else
692 {
693 wcscpy(szName, wFileName);
694 }
695 }
696 else
697 {
698 Length = wcslen(pOffset);
699 if (Length >= 100)
700 return 0;
701 wcscpy(szName, pOffset);
702 }
703 TRACE("EnumPropSheetExt szName %s\n", debugstr_w(szName));
704 hpsxa[0] = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, szName, NumPages, pDataObj);
705 Pages = SHAddFromPropSheetExtArray(hpsxa[0], AddShellPropSheetExCallback, (LPARAM)hppages);
706
707
708 if (pOffset)
709 {
710 /* try to load property sheet handlers from prog id key */
711 dwName = sizeof(szName);
712 if (RegGetValueW(HKEY_CLASSES_ROOT, pOffset, NULL, RRF_RT_REG_SZ, NULL, szName, &dwName) == ERROR_SUCCESS)
713 {
714 TRACE("EnumPropSheetExt szName %s, pOffset %s\n", debugstr_w(szName), debugstr_w(pOffset));
715 szName[(sizeof(szName)/sizeof(WCHAR))-1] = L'\0';
716 hpsxa[1] = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, szName, NumPages - Pages, pDataObj);
717 Pages +=SHAddFromPropSheetExtArray(hpsxa[1], AddShellPropSheetExCallback, (LPARAM)hppages);
718 }
719 }
720 return Pages;
721 }
722
723
724
725 /*************************************************************************
726 *
727 * SH_ShowPropertiesDialog
728 *
729 * called from ShellExecuteExW32
730 *
731 * lpf contains (quoted) path of folder/file
732 *
733 * TODO: provide button change application type if file has registered type
734 * make filename field editable and apply changes to filename on close
735 */
736
737 BOOL
738 SH_ShowPropertiesDialog(PCWSTR lpf)
739 {
740 PROPSHEETHEADERW pinfo;
741 HPROPSHEETPAGE hppages[MAX_PROPERTY_SHEET_PAGE];
742 HPROPSHEETPAGE hpage;
743 WCHAR wFileName[MAX_PATH];
744 UINT num_pages = 0;
745 DWORD dwHandle = 0;
746 WCHAR * pFileName;
747 HPSXA hpsxa[2];
748 INT_PTR res;
749 LPITEMIDLIST pidlChild, pidlFolder;
750 WCHAR szTemp[MAX_PATH];
751 IDataObject* pDataObj = NULL;
752 HRESULT hResult;
753
754 TRACE("SH_ShowPropertiesDialog entered filename %s\n", debugstr_w(lpf));
755
756 if (lpf== NULL)
757 return FALSE;
758
759 if ( !strlenW(lpf) )
760 return FALSE;
761
762 memset(hppages, 0x0, sizeof(HPROPSHEETPAGE) * MAX_PROPERTY_SHEET_PAGE);
763 if (lpf[0] == '"')
764 {
765 /* remove quotes from lpf */
766 LPCWSTR src = lpf + 1;
767 LPWSTR dst = wFileName;
768
769 while(*src && *src!='"')
770 *dst++ = *src++;
771
772 *dst = '\0';
773 }
774 else
775 {
776 strcpyW(wFileName, lpf);
777 }
778
779 if (PathIsDirectoryW(wFileName))
780 {
781 return SH_ShowFolderProperties(wFileName);
782 }
783
784 if (wcslen(wFileName) == 3)
785 {
786 return SH_ShowDriveProperties(wFileName);
787 }
788
789 wcscpy(szTemp, wFileName);
790 pFileName = wcsrchr(szTemp, '\\');
791 if (pFileName)
792 {
793 pFileName[0] = L'\0';
794 pFileName++;
795 pidlChild = ILCreateFromPathW(pFileName);
796 pidlFolder = ILCreateFromPathW(szTemp);
797 if (pidlChild && pidlFolder)
798 {
799 hResult = SHCreateDataObject(pidlFolder, 1, (LPCITEMIDLIST*)&pidlChild, NULL, &IID_IDataObject, (LPVOID*)&pDataObj);
800 ILFree(pidlChild);
801 ILFree(pidlFolder);
802 if (hResult != S_OK)
803 pDataObj = NULL;
804 }
805 }
806
807
808 hpage = SH_CreatePropertySheetPage("SHELL_FILE_GENERAL_DLG", SH_FileGeneralDlgProc, (LPARAM)wFileName, NULL);
809
810 if (hpage == NULL)
811 return FALSE;
812
813 hppages[num_pages] = hpage;
814 num_pages++;
815 num_pages += EnumPropSheetExt(wFileName, hppages, MAX_PROPERTY_SHEET_PAGE-1, hpsxa, pDataObj);
816
817 if ( GetFileVersionInfoSizeW(lpf, &dwHandle) && num_pages)
818 {
819 if ( (hpage = SH_CreatePropertySheetPage("SHELL_FILE_VERSION_DLG",SH_FileVersionDlgProc, (LPARAM)wFileName, NULL))!= NULL)
820 {
821 hppages[num_pages] = hpage;
822 num_pages++;
823 }
824 }
825
826 pFileName = wcsrchr(wFileName, '\\');
827 if (!pFileName)
828 pFileName = wFileName;
829 else
830 pFileName++;
831
832
833 memset(&pinfo, 0x0, sizeof(PROPSHEETHEADERW));
834 pinfo.dwSize = sizeof(PROPSHEETHEADERW);
835 pinfo.dwFlags = PSH_NOCONTEXTHELP | PSH_PROPTITLE;
836 pinfo.nPages = num_pages;
837 pinfo.u3.phpage = hppages;
838 pinfo.pszCaption = pFileName;
839
840 TRACE("SH_ShowPropertiesDialog pages %u\n", num_pages);
841 res = PropertySheetW(&pinfo);
842
843 SHDestroyPropSheetExtArray(hpsxa[0]);
844 SHDestroyPropSheetExtArray(hpsxa[1]);
845 if (pDataObj)
846 IDataObject_Release(pDataObj);
847
848 return (res != -1);
849 }
850 /*EOF */