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