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