uLib  User mode C/C++ extended API library for Win32 programmers.
ShellUtil.cpp
Go to the documentation of this file.
1 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2 // Project: uLib - User mode library.
3 // Module: Shell utility functions (Migrated from UtilFunc.cpp)
4 // Author: Copyright (c) Love Nystrom
5 // License: NNOSL (BSD descendant, see NNOSL.txt in the base directory).
6 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7 
8 #include <uLib/Common.h>
9 #include <uLib/UtilFunc.h>
10 #include <uLib/Debug.h>
11 #include <uLib/StrFunc.h>
12 
13 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
14 // Shell
15 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
16 
17 IMalloc* ShMalloc = NULL; // Hint: Init/free in MainWnd. Lifespan == program.
18 
19 static WORD shFlags = 0;
20 #define SHF_INITIALIZED 0x0001
21 #define SHF_USE_OLE 0x0002
22 #define SHF_SHMALLOC 0x0004
23 
25 {
26  return BITS_SET( SHF_INITIALIZED, shFlags );
27 }
28 
29 static HRESULT _initShMalloc()
30 {
31  HRESULT rc = CoGetMalloc( MEMCTX_TASK, &ShMalloc );
32  if (SUCCEEDED( rc )) shFlags |= SHF_SHMALLOC;
33  else DPrint( DP_ERROR, _F("CoGetMalloc failed: %s\n"), SysErrorMsg( rc ));
34  return rc;
35 }
36 
37 bool InitShellFunc( bool useOle, DWORD coFlag )
38 {
39  HRESULT rc = 0;
40  if (0 == (shFlags & SHF_INITIALIZED))
41  {
42  if (useOle)
43  {
44  rc = OleInitialize( NULL );
45  if (SUCCEEDED( rc )) shFlags |= (SHF_INITIALIZED | SHF_USE_OLE);
46  else DPrint( DP_ERROR, _F("OleInitialize failed: %s\n"), SysErrorMsg( rc ));
47  }
48  else
49  {
50  rc = CoInitializeEx( NULL, coFlag ); //COINIT_APARTMENTTHREADED| COINIT_SPEED_OVER_MEMORY
51  // Memo: COINIT_MULTITHREADED is not the average case..
52  if (SUCCEEDED( rc )) shFlags |= SHF_INITIALIZED;
53  else DPrint( DP_ERROR, _F("CoInitializeEx failed: %s\n"), SysErrorMsg( rc ));
54  }
55  }
56  if (0 == (shFlags & SHF_SHMALLOC))
57  {
58  rc = _initShMalloc();
59  }
60  if (FAILED( rc )) SetLastError( rc );
61  return SUCCEEDED( rc );
62 }
63 
65 {
66  if (shFlags & SHF_SHMALLOC)
67  {
68  ShMalloc->Release();
69  ShMalloc = NULL;
70  }
71  if (shFlags & SHF_INITIALIZED)
72  {
73  if (shFlags & SHF_USE_OLE) OleUninitialize();
74  else CoUninitialize();
75  }
76  shFlags = 0;
77 }
78 
79 PVOID ShellFreeEx( PVOID pBlk )
80 {
81  if (pBlk)
82  {
83  if (!ShMalloc) _initShMalloc();
84  if (ShMalloc)
85  {
86  ShMalloc->Free( pBlk );
87  pBlk = NULL;
88  }
89  }
90  return pBlk;
91 }
92 
93 /* Alphatest for GetPathNamePIDL:
94  InitShellFunc();
95  TCHAR sBuf[ MAX_PATH ];
96  ULONG Attr = SFGAO_FILESYSTEM;
97 
98  LPITEMIDLIST pIdl = GetPathNamePIDL( "C:\\Windows\\System32", &Attr ); // <<==--
99 
100  if (SHGetPathFromIDList( pIdl, sBuf ))
101  printf( "pIdl = '%s' {0x%08X}\n", sBuf, Attr );
102  pIdl = ShellFreeEx( pIdl );
103  DoneShellFunc();
104 */
105 LPITEMIDLIST GetPathNamePIDL( CSTR Dir, ULONG* pAttrib )
106 {
107  IShellFolder* pShell;
108  ULONG chUsed; //, attrib = SFGAO_FILESYSTEM;
109  LPITEMIDLIST pidl = NULL;
110 
111  if (SUCCEEDED( SHGetDesktopFolder( &pShell )))
112  {
113  #ifdef _UNICODE
114  #define wPath (PWSTR)Dir
115  #else
116  WCHAR wPath[ MAX_PATH ];
117  MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, Dir,-1, wPath, MAX_PATH );
118  #endif
119  // Convert the Unicode path to an ITEMIDLIST.
120  bool ok = SUCCEEDED(
121  pShell->ParseDisplayName(
122  (HWND)NULL, (IBindCtx*)NULL, wPath, &chUsed, &pidl, pAttrib
123  ));
124  if (!ok) pidl = NULL;
125  pShell->Release();
126  }
127  return pidl;
128 }
129 
130 bool RecycleFile( CSTR Name, bool Confirm, bool Single ) // Move file(s) to the trash can.
131 {
132  SHFILEOPSTRUCT fop;
133  IF_DEBUG( memset( &fop, 0, sizeof(fop) ));
134 
135  fop.wFunc = FO_DELETE;
136 
137  // Leverage the fact that newStr always overallocate by 1 char,
138  // precisely for the purpose of easy double-NUL termination.
139 
140  fop.pFrom = Single ? newStr( Name ) : Name;
141  if (!fop.pFrom) return false;
142 
143  fop.fFlags = FOF_ALLOWUNDO| FOF_FILESONLY| FOF_NO_CONNECTED_ELEMENTS;
144  if (!Confirm) fop.fFlags |= FOF_NOCONFIRMATION;
145  fop.hwnd = hMainWnd;
146 
147  int rc = SHFileOperation( &fop );
148 
149  if (Single) deleteStr( fop.pFrom );
150  if (rc) SetLastError( rc ); // Note: For debugging.. See MSDN SHFileOperation.
151  return ((rc == 0) && !fop.fAnyOperationsAborted);
152 }
153 
154 // Return the packed version number of a DLL, or 0 if it doesn't export DllGetVersion.
155 
157 {
158  DWORD ver = 0; // Assume failure some way or another...
159  HINSTANCE hlib = LoadLibrary( FName );
160  if (hlib)
161  {
162  HRESULT (CALLBACK *DllGetVersion)( DLLVERSIONINFO* );
163  (FARPROC&) DllGetVersion = GetProcAddress( hlib, "DllGetVersion" );
164  if (DllGetVersion)
165  {
166  DLLVERSIONINFO vi; IF_DEBUG( memset( &vi, 0, sizeof(vi) ));
167  vi.cbSize = sizeof(DLLVERSIONINFO);
168  bool ok = SUCCEEDED( DllGetVersion( &vi ));
169  if (ok) ver = PACKVERSION( vi.dwMajorVersion, vi.dwMinorVersion );
170  }
171  FreeLibrary( hlib );
172  }
173  return ver;
174 }
175 
176 // Create a shell link file.
177 // Based on a public Microsoft example.
178 // (For some mysterious reason, doxygen excludes the code for this)
179 
180 HRESULT Shell_CreateLink( CSTR LinkFilePathname, const PLINKDATA pd )
181 {
182  HRESULT hres;
183  IShellLink* ShLink;
184  IPersistFile* File;
185 
186  if (!IsString( LinkFilePathname ) || !pd || !pd->Pathname)
187  return E_INVALIDARG; //HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
188 
189  bool _inited = ShellFuncInitialized();
190  if (!_inited) hres = CoInitialize( NULL );
191 
192  // Create a shell link object
193 
194  hres = CoCreateInstance (
195  CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
196  IID_IShellLink, (void**)&ShLink
197  );
198  if (SUCCEEDED( hres )) // Initialize the shell link object
199  {
200  ShLink->SetPath( pd->Pathname );
201 
202  if (pd->Flags & LDF_ARGS) ShLink->SetArguments( pd->Args );
203  if (pd->Flags & LDF_DESC) ShLink->SetDescription( pd->Desc );
204  if (pd->Flags & LDF_SHOWCMD) ShLink->SetShowCmd( pd->ShowCmd );
205  if (pd->Flags & LDF_HOTKEY) ShLink->SetHotkey( pd->Hotkey );
206  if (pd->Flags & LDF_PIDL) ShLink->SetIDList( pd->IdList );
207 
208  if (pd->Flags & LDF_ICON)
209  ShLink->SetIconLocation( pd->IconPath, pd->IconIndex );
210 
211  if (pd->Flags & LDF_WORKDIR)
212  ShLink->SetWorkingDirectory( pd->WorkingDir );
213 
214  // Save the shell link object to disk
215 
216  hres = ShLink->QueryInterface( IID_IPersistFile, (void**)&File );
217  if (SUCCEEDED( hres ))
218  {
219  #ifdef _UNICODE
220  hres = File->Save( LinkFilePathname, true );
221  #else // Convert the ANSI path to a Unicode path
222  WCHAR wzPath[ MAX_PATH ] = {0};
223  MultiByteToWideChar( CP_ACP,0, LinkFilePathname,-1, wzPath,MAX_PATH );
224  hres = File->Save( wzPath, true );
225  #endif
226  File->Release();
227  }
228  ShLink->Release();
229  }
230 
231  if (!_inited) CoUninitialize();
232  return hres;
233 }
234 
235 // Resolve a shell "lnk" file.
236 // Based on a public Microsoft example.
237 // (For some mysterious reason, doxygen excludes the code for this)
238 
239 HRESULT Shell_ResolveLink( HWND hWnd, CSTR LinkFile, PLINKDATA pd )
240 {
241  HRESULT hres;
242  IShellLink* ShLink;
243  IPersistFile* File;
244  WIN32_FIND_DATA fd;
245 
246  if (!IsString( LinkFile ) || !pd)
247  return E_INVALIDARG; //HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
248 
249  *pd->Pathname = 0; // Assume failure
250 
251  bool _inited = ShellFuncInitialized();
252  if (!_inited) hres = CoInitialize( NULL );
253 
254  hres = CoCreateInstance(
255  CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
256  IID_IShellLink, (void**)&ShLink//psl
257  );
258  if (SUCCEEDED( hres ))
259  {
260  hres = ShLink->QueryInterface( IID_IPersistFile, (void**)&File ); //ppf
261  if (SUCCEEDED( hres ))
262  {
263  #ifdef _UNICODE
264  #define wszLink LinkFile
265  #else
266  WCHAR wszLink[ MAX_PATH ];
267  MultiByteToWideChar( CP_ACP, 0, LinkFile,-1, wszLink, MAX_PATH );
268  // PONDER: Add code to check MultiByteToWideChar for success.
269  #endif
270  hres = File->Load( wszLink, STGM_READ );
271  if (SUCCEEDED( hres ))
272  {
273  //hres = ShLink->Resolve( hWnd, SLR_NOUPDATE ); // Resolve the link.
274  hres = ShLink->Resolve( hWnd, 0 ); // Resolve the link.
275  if (SUCCEEDED( hres ))
276  {
277  hres = ShLink->GetPath(
278  pd->Pathname, MAX_PATH, &fd, SLGP_SHORTPATH
279  );
280  if (SUCCEEDED( hres ))
281  {
282  if (pd->Flags & LDF_DESC)
283  hres = ShLink->GetDescription(
284  pd->Desc, MAX_PATH
285  );
286  if (pd->Flags & LDF_ARGS)
287  hres = ShLink->GetArguments(
288  pd->Args, MAX_PATH
289  );
290  if (pd->Flags & LDF_ICON)
291  hres = ShLink->GetIconLocation(
292  pd->IconPath, MAX_PATH, &pd->IconIndex
293  );
294  if (pd->Flags & LDF_WORKDIR)
295  hres = ShLink->GetWorkingDirectory(
296  pd->WorkingDir, MAX_PATH
297  );
298 
299  if (pd->Flags & LDF_PIDL)
300  hres = ShLink->GetIDList( &pd->IdList );
301  if (pd->Flags & LDF_HOTKEY)
302  hres = ShLink->GetHotkey( &pd->Hotkey );
303  if (pd->Flags & LDF_SHOWCMD)
304  hres = ShLink->GetShowCmd( &pd->ShowCmd );
305  }
306  }
307  }
308  File->Release();
309  }
310  ShLink->Release();
311  }
312 
313  if (!_inited) CoUninitialize();
314  return hres;
315 }
316 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
317 //void AlphatestShellLink()
318 //{
319 // #ifndef MAKE_HOTKEY
320 // #define MAKE_HOTKEY( key,flags ) (WORD)((flags) << 8) | key
321 // #endif
322 //
323 // HRESULT hr;
324 // CCSTR linkname = MY_ULIBDIR "\\RosIDE (dbg).lnk";
325 // LINKDATA ld = {0};
326 //
327 // ld.Flags = LDF_ALL & ~LDF_PIDL;
328 // ld.IconIndex = 0;
329 // ld.ShowCmd = SW_SHOWNORMAL;
330 // ld.Hotkey = MAKE_HOTKEY( 'Q', HOTKEYF_ALT| HOTKEYF_CONTROL ); // Alt-Ctrl-Q
331 //
332 // ld.Pathname = newStrBuf( MAX_PATH );
333 // ld.Desc = newStrBuf( MAX_PATH );
334 // ld.Args = newStrBuf( MAX_PATH );
335 // ld.IconPath = newStrBuf( MAX_PATH );
336 // ld.WorkingDir = newStrBuf( MAX_PATH );
337 //
338 // BEGIN_STRSAFE_OVERRIDE
339 // strcpy( ld.Pathname, MY_IDEDIR "\\vs2oo8\\Debug\\RosIDE.exe" );
340 // strcpy( ld.WorkingDir, MY_IDEDIR "\\" );
341 // strcpy( ld.IconPath, ld.Pathname );
342 // strcpy( ld.Args, "/test /link" );
343 // strcpy( ld.Desc, "ReactOS Integrated Development Environment" );
344 // END_STRSAFE_OVERRIDE
345 //
346 // hr = Shell_CreateLink( linkname, &ld ); // Ok
347 //
348 // memset( ld.Pathname, 0, _TBYTES( MAX_PATH ));
349 // memset( ld.Desc, 0, _TBYTES( MAX_PATH ));
350 // memset( ld.Args, 0, _TBYTES( MAX_PATH ));
351 // memset( ld.IconPath, 0, _TBYTES( MAX_PATH ));
352 // memset( ld.WorkingDir, 0, _TBYTES( MAX_PATH ));
353 // ld.IconIndex = ld.ShowCmd = ld.Hotkey = 0;
354 // ld.Flags |= LDF_PIDL;
355 //
356 // hr = Shell_ResolveLink( hMainWnd, linkname, &ld ); // Ok
357 //
358 // TCHAR pidlPath[ MAX_PATH ] = {0};
359 // if (SHGetPathFromIDList( ld.IdList, pidlPath ))
360 // DPrint( DP_DEBUG, "PIDL: '%s'\n", pidlPath );
361 //
362 // ShellFreeEx( ld.IdList );
363 //}
364 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
365 
367 
368 HRESULT ShowShareFolderUI( HWND hParent, CSTR Path )
369 {
370  HRESULT hres;
371  // Note: This function has no associated .lib file.
372  static HRESULT (NTAPI *_ShowShareFolderUI)( HWND hParent, LPCWSTR wzPath );
373  if (!_ShowShareFolderUI)
374  {
375  HMODULE hMod = LoadLibraryA( "ntshrui.dll" );
376  if (hMod) (FARPROC&)_ShowShareFolderUI = GetProcAddress( hMod, "ShowShareFolderUI" );
377  TRACE( DP_DEBUG, _F("_ShowShareFolderUI = %p\n"), _ShowShareFolderUI );
378  }
379  if (!_ShowShareFolderUI) hres = E_FAIL;
380  else
381  {
382  #ifdef _UNICODE
383  #define wzPath Path
384  #else
385  WCHAR wzPath[ MAX_PATH ];
386  MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, Path, -1, wzPath, dimof(wzPath) );
387  #endif
388  hres = _ShowShareFolderUI( hParent, wzPath );
389  }
390  return hres;
391 }
392 
393 // This one pre-dates SHCreateStreamOnFile (which has more options).
394 
395 HRESULT CreateStreamOnFile( _in CSTR FName, _out IStream** ppStrm, _out DWORD* pSize )
396 {
397  ULARGE_INTEGER fsize;
398  MEMORYSTATUSEX mems;
399  HANDLE hGlb, hFile;
400  PVOID pGlb;
401  DWORD cbRd, dwSize;
402 
403  HRESULT hr = 0;
404 
405  memset( &mems, 0, sizeof(mems) );
406  mems.dwLength = sizeof(mems);
407  if (!GlobalMemoryStatusEx( &mems )) mems.ullAvailPhys = 0;
408 
409  hFile = CreateFile( FName, GENERIC_RW, 0,0, OPEN_EXISTING, 0,0 );
410  if (BAD_HANDLE( hFile ))
411  hr = HRESULT_FROM_WIN32( GetLastError() ); // E.g. Access denied
412  else
413  {
414  fsize.LowPart = GetFileSize( hFile, &fsize.HighPart );
415 
416  // Limit allowed file size to DWORD range and 1/2 of available RAM.
417  // Using ullAvailVirtual here would be pointless, since we want pure RAM access.
418  // The DWORD range is because ReadFile return cbRead only that large,
419  // and 1/2 a "somewhat reasonable" (agh) runtime limit for extreme cases.
420 
421  mems.ullAvailPhys /= 2;
422  if (fsize.HighPart || (fsize.QuadPart > mems.ullAvailPhys))
423  hr = E_OUTOFMEMORY; //HRESULT_FROM_WIN32( ERROR_OUTOFMEMORY );
424  else
425  {
426  dwSize = fsize.LowPart; // Abbreviate
427  if (pSize) *pSize = dwSize;
428 
429  hGlb = GlobalAlloc( GMEM_MOVEABLE| GMEM_SHARE, dwSize );
430  if (!hGlb) hr = E_OUTOFMEMORY;
431  else
432  {
433  pGlb = GlobalLock( hGlb );
434  if (!pGlb) hr = E_HANDLE;
435  else
436  {
437  if (!ReadFile( hFile, pGlb, dwSize, &cbRd, 0 ) || (cbRd != dwSize))
438  hr = HRESULT_FROM_WIN32( GetLastError() );
439 
440  GlobalUnlock( hGlb );
441  if (SUCCEEDED( hr ))
442  {
443  hr = CreateStreamOnHGlobal( hGlb, TRUE, ppStrm );
444  }
445  // CreateStreamOnHGlobal initially determines the stream size
446  // by GlobalSize, so call IStream::SetSize, since the exact
447  // stream size is probably rather important to the caller.
448 
449  if (SUCCEEDED( hr )) hr = (*ppStrm)->SetSize( fsize );
450  }
451  if (FAILED( hr )) GlobalFree( hGlb );
452  }
453  }
454  CloseHandle( hFile );
455  }
456  return hr;
457 }
458 
459 #if 0 // In the odd case you need an IStream on an HMAPFILE (I can't really see why).
460 
466 IStream* CreateStreamOnMappedFile( CSTR FName, DWORD PageAccess, HMAPFILE* phFile )
467 {
468  IStream* pStream = NULL;
469  PBYTE pData = NULL;
470 
471  HMAPFILE hFile = LoadAndMapFile( FName, PageAccess, &pData );
472  UINT cbData = hFile ? (UINT) GetMappedSize( hFile ) : 0;
473 
474  #if (_WIN32_IE >= 0x600)
475  if (pData) pStream = SHCreateMemStream( pData, cbData );
476  #else
477  if (pData)
478  {
479  // Prior to Windows Vista, this function was not included in the public Shlwapi.h file,
480  // nor was it exported by name from Shlwapi.dll. To use it on earlier systems, you must
481  // call it directly from the Shlwapi.dll file as ordinal 12.
482 
483  static IStream* (__stdcall *_SHCreateMemStream)( const PBYTE pInit, UINT cbInit );
484  if (!_SHCreateMemStream)
485  {
486  HMODULE hLib = LoadLibrary( _T("SHLWAPI.DLL") );
487  if (hLib) (FARPROC&)_SHCreateMemStream = GetProcAddress( hLib, CSTR( 12 ));
488  }
489  if (_SHCreateMemStream) pStream = _SHCreateMemStream( pData, cbData );
490  }
491  #endif
492 
493  if (phFile) *phFile = hFile;
494  return pStream;
495 }
496 
498 
499 void ReleaseMappedFileStream( IStream* pStm, HMAPFILE hFile )
500 {
501  RELEASE_OBJ( pStm );
502  UnloadMappedFile( hFile );
503 }
504 #endif
505 
506 #if USE_VISUALSTYLE_HACK
507 
508 bool EnableVisualStyles( bool Enable )
509 {
510  static ULONG_PTR actCookie; // = FALSE;
511  static const UINT_PTR shellManifestId = 124;
512 
513  BOOL ok = FALSE;
514  if (Enable)
515  {
516  if (actCookie) ok = TRUE; // Already activated
517  else {
518  // Enable visual styles by using the manifest in SHELL32.DLL.
519  TCHAR sysDir[ MAX_PATH ];
520  ACTCTX actCtx = {
521  sizeof(actCtx),
522  ACTCTX_FLAG_RESOURCE_NAME_VALID
523  | ACTCTX_FLAG_SET_PROCESS_DEFAULT
524  | ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID,
525  _T("shell32.dll"), 0,0,
526  sysDir, (CSTR)shellManifestId, NULL, NULL
527  };
528  UINT cch = GetSystemDirectory( sysDir, dimof(sysDir) );
529  if (cch < dimof(sysDir)) { // Should always succeed
530  sysDir[cch] = 0;
531  HANDLE hActCtx = CheckHandle( CreateActCtx( &actCtx ));
532  ok = hActCtx ? ActivateActCtx( hActCtx, &actCookie ) : FALSE;
533  }
534  }
535  }
536  else if (actCookie)
537  {
538  #ifdef HAVE_STRUCTURED_EH
539  __try {
540  ok = DeactivateActCtx( 0, actCookie );
541  if (ok) actCookie = 0; // Invalidate
542  }
544  DWORD xCode = GetExceptionCode(); //STATUS_SXS_EARLY_DEACTIVATION / STATUS_SXS_INVALID_DEACTIVATION
545  TRACE( DP_ERROR, _F("Exception %#x.\n"), xCode );
546  ok = FALSE;
547  }
548  __end_except;
549  #else // __GNUC__; No SEH
550  ok = DeactivateActCtx( 0, actCookie );
551  if (ok) actCookie = 0; // Invalidate
552  #endif // _MSC_VER
553  }
554  return bool_cast( ok );
555 }
556 #endif
557 
558 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
559 // Tray support
560 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
561 
563 
564 #if 0 // This omission have been already been mended by MinGW.
565 #ifdef __GNUC__
566  #if (WINVER >= 0x601)
567  #error("FIXME: MinGW's user32 lib lacks ChangeWindowMessageFilter") // See below...
568  #endif
569  WINUSERAPI BOOL WINAPI
570  ChangeWindowMessageFilter( UINT message, DWORD dwFlag );
571  #define MSGFLT_ADD 1
572  #define MSGFLT_REMOVE 2
573 #endif // __GNUC__
574 #endif
575 
577 {
578  WM_TaskbarCreated = RegisterWindowMessage( _T("TaskbarCreated") );
579 
580  // Some bozo at MS thought it a good idea to block TaskbarCreated
581  // with User Interface Privilege Isolation, apparently not realizing
582  // this will rumpfuck any "non-admin" app that uses tray icons, every
583  // time Explorer crashes and has to restart (which is none too rare
584  // given the plethora of less-than-perfect shell extenders around).
585  // What a blooper :/
586 
587  #if WINVER >= 0x601
588  if (IsWin7()) { // Are we on Win7++ ?
589  TRACE( DP_DEBUG, _T("Windows 7++ : Unblocking WM_TaskbarCreated.\n") );
590  CHANGEFILTERSTRUCT cfs = { sizeof(CHANGEFILTERSTRUCT), 0 };
591  ChangeWindowMessageFilterEx( hMainWnd, WM_TaskbarCreated, MSGFLT_ALLOW, &cfs );
592  }
593  #ifndef __GNUC__
594  else // If WINVER==x601 and __GNUC__ this would become a spurious 'else' (see above).
595  #endif
596  #endif
597  #if (WINVER >= 0x600) && !defined(__GNUC__) // MinGW's user32 lib lacks this API
598  if (IsWinVista()) { // Are we on Vista++ ?
599  TRACE( DP_DEBUG, _T("Windows Vista++ : Unblocking WM_TaskbarCreated.\n") );
600  ChangeWindowMessageFilter( WM_TaskbarCreated, MSGFLT_ADD );
601  }
602  #endif
603 }
604 
605 // Was e.g: ShellNotify( hMainWnd, NIM_ADD, Icons[0], "Remind Me", WM_APP );
606 
608  UINT Action, HWND hNfy, UINT Id, HICON hIcon, CSTR Hint, UINT cbkMsg
609  )
610 {
611  NOTIFYICONDATA nic;
612 
613  nic.cbSize = sizeof(nic);
614  nic.hWnd = hNfy;
615  nic.uID = Id;
616 
617  switch( Action )
618  {
619  case NIM_ADD:
620  case NIM_MODIFY:
621  nic.hIcon = hIcon;
622  nic.uCallbackMessage = cbkMsg;
623  nic.uFlags = NIF_ICON | NIF_MESSAGE;
624  if (Hint)
625  {
626  _tcscpy_s( nic.szTip, dimof(nic.szTip), Hint );
627  nic.uFlags |= NIF_TIP;
628  }
629  break;
630 
631  default:
632  nic.uFlags = 0;
633  break;
634  }
635  return Shell_NotifyIcon( Action, &nic );
636 }
637 
638 // EOF
#define RELEASE_OBJ(Ifc)
Definition: Common.h:994
unsigned long DWORD
Definition: Common.h:414
DWORD GetDLLVersion(CSTR FName)
Definition: ShellUtil.cpp:156
HANDLE CheckHandle(HANDLE Hnd)
Definition: KernelUtil.cpp:75
void InitTaskbarSupport()
Definition: ShellUtil.cpp:576
bool IsWin7()
Definition: Common.cpp:92
#define CSTR
Definition: Common.h:329
unsigned short WORD
Definition: Common.h:413
#define LDF_SHOWCMD
Definition: UtilFunc.h:270
#define IF_DEBUG(code)
Definition: Debug.h:236
bool IsWinVista()
Definition: Common.cpp:93
#define LDF_PIDL
Definition: UtilFunc.h:271
#define DP_DEBUG
Definition: Debug.h:85
CSTR newStr(CSTR Src)
Definition: StrFunc.cpp:167
unsigned char * PBYTE
Definition: Common.h:412
bool InitShellFunc(bool useOle, DWORD coFlag)
Definition: ShellUtil.cpp:37
#define dimof(x)
Definition: Common.h:949
void __cdecl DPrint(int Level, CSTR Fmt,...)
Definition: Debug.cpp:134
#define SHF_USE_OLE
Definition: ShellUtil.cpp:21
#define TRACE(_lvl,...)
Definition: Debug.h:216
#define _in
Definition: Common.h:253
HRESULT ShowShareFolderUI(HWND hParent, CSTR Path)
Transmutable wrap for the strictly dynamic ntshrui.dll function.
Definition: ShellUtil.cpp:368
UINT WM_TaskbarCreated
Definition: ShellUtil.cpp:562
#define GetMappedSize
Definition: UtilFunc.h:2766
HRESULT CreateStreamOnFile(_in CSTR FName, _out IStream **ppStrm, _out DWORD *pSize)
Definition: ShellUtil.cpp:395
HRESULT Shell_CreateLink(CSTR LinkFilePathname, const PLINKDATA pd)
Definition: ShellUtil.cpp:180
bool ShellFuncInitialized()
Definition: ShellUtil.cpp:24
#define __except_execute
Definition: Common.h:647
HANDLE HMAPFILE
Definition: UtilFunc.h:2732
#define PACKVERSION(maj, min)
Definition: UtilFunc.h:236
BOOL(WINAPI *SysImgList::Shell_GetImageLists)(HIMAGELIST *pimlLarge
struct _LINKDATA * PLINKDATA
#define LDF_DESC
Definition: UtilFunc.h:265
CSTR SysErrorMsg(DWORD Err=0, TSTR Buf=NULL, UINT Length=0)
Definition: Debug.cpp:39
PVOID ShellFreeEx(PVOID pBlk)
Definition: ShellUtil.cpp:79
#define LDF_WORKDIR
Definition: UtilFunc.h:268
#define GENERIC_RW
Definition: Common.h:1128
#define SHF_SHMALLOC
Definition: ShellUtil.cpp:22
#define LDF_ARGS
Definition: UtilFunc.h:266
#define LDF_HOTKEY
Definition: UtilFunc.h:269
BOOL UnloadMappedFile(HMAPFILE hMap)
Definition: IoUtil.cpp:1234
bool __forceinline bool_cast(BOOL B52)
Definition: Common.h:767
LPITEMIDLIST GetPathNamePIDL(CSTR Dir, ULONG *pAttrib)
Definition: ShellUtil.cpp:105
#define DP_ERROR
Definition: Debug.h:82
#define BITS_SET(bits, x)
Definition: Common.h:1016
Debug and error handling support.
#define _out
Definition: Common.h:254
HRESULT Shell_ResolveLink(HWND hWnd, CSTR LinkFile, PLINKDATA pd)
Definition: ShellUtil.cpp:239
Common include; Added types, small "ubiquitous" utilities, et c.
IMalloc * ShMalloc
Definition: ShellUtil.cpp:17
HMAPFILE LoadAndMapFile(CSTR FName, DWORD PageAccess, PBYTE *ppData)
Definition: IoUtil.cpp:1152
#define _F(s)
Definition: Debug.h:49
void DoneShellFunc()
Definition: ShellUtil.cpp:64
#define BAD_HANDLE(hnd)
Definition: Common.h:1004
bool RecycleFile(CSTR Name, bool Confirm, bool Single)
Definition: ShellUtil.cpp:130
CSTR deleteStr(CSTR Dup)
Definition: StrFunc.cpp:191
HWND hMainWnd
Definition: Common.cpp:12
#define SHF_INITIALIZED
Definition: ShellUtil.cpp:20
BOOL SetTrayIconNotification(UINT Action, HWND hNfy, UINT Id, HICON hIcon, CSTR Hint, UINT cbkMsg)
Definition: ShellUtil.cpp:607
bool __forceinline IsString(CSTR Str)
Definition: StrFunc.h:84
#define LDF_ICON
Definition: UtilFunc.h:267