@@ -47,11 +47,10 @@ static void
4747ModifyShellContextMenu (IContextMenu * pCM , HMENU hMenu , UINT CmdIdFirst , PCWSTR Assoc )
4848{
4949 HRESULT hr ;
50- UINT id , i ;
51- for (i = 0 ; i < GetMenuItemCount (hMenu ); ++ i )
50+ for (UINT i = 0 , c = GetMenuItemCount (hMenu ); i < c ; ++ i )
5251 {
5352 WCHAR buf [200 ];
54- id = GetMenuItemIdByPos (hMenu , i );
53+ UINT id = GetMenuItemIdByPos (hMenu , i );
5554 if (id == (UINT )- 1 )
5655 continue ;
5756
@@ -131,28 +130,119 @@ DoShellContextMenu(HWND hwnd, IContextMenu *pCM, PCWSTR File, LPARAM lParam)
131130 g_pContextMenu = NULL ;
132131}
133132
134- void
135- DoShellContextMenuOnFile (HWND hwnd , PCWSTR File , LPARAM lParam )
133+ HRESULT
134+ GetUIObjectOfPath (HWND hwnd , PCWSTR File , REFIID riid , void * * ppv )
136135{
137136 HRESULT hr ;
138137 IShellFolder * pSF ;
139138 PCUITEMID_CHILD pidlItem ;
140139 PIDLIST_ABSOLUTE pidl = ILCreateFromPath (File );
141140 if (pidl && SUCCEEDED (SHBindToParent (pidl , IID_PPV_ARG (IShellFolder , & pSF ), & pidlItem )))
142141 {
143- IContextMenu * pCM ;
144- hr = IShellFolder_GetUIObjectOf (pSF , hwnd , 1 , & pidlItem , & IID_IContextMenu , NULL , (void * * )& pCM );
142+ hr = IShellFolder_GetUIObjectOf (pSF , hwnd , 1 , & pidlItem , riid , NULL , ppv );
143+ IShellFolder_Release (pSF );
144+ }
145+ SHFree (pidl );
146+ return hr ;
147+ }
148+
149+ void
150+ DoShellContextMenuOnFile (HWND hwnd , PCWSTR File , LPARAM lParam )
151+ {
152+ IContextMenu * pCM ;
153+ HRESULT hr = GetUIObjectOfPath (hwnd , File , IID_PPV_ARG (IContextMenu , & pCM ));
154+ if (SUCCEEDED (hr ))
155+ {
156+ DoShellContextMenu (hwnd , pCM , File , lParam );
157+ IContextMenu_Release (pCM );
158+ }
159+ }
160+
161+ typedef struct _ENABLECOMMANDDATA
162+ {
163+ HWND hwnd ;
164+ PCWSTR Verb ;
165+ UINT CmdId ;
166+ UINT ImageId ;
167+ WCHAR File [ANYSIZE_ARRAY ];
168+ } ENABLECOMMANDDATA ;
169+
170+ static DWORD CALLBACK
171+ EnableCommandIfVerbExistsProc (LPVOID ThreadParam )
172+ {
173+ enum { first = 1 , last = 0x7fff };
174+ ENABLECOMMANDDATA * pData = ThreadParam ;
175+ IContextMenu * pCM ;
176+ HRESULT hr = GetUIObjectOfPath (pData -> hwnd , pData -> File , IID_PPV_ARG (IContextMenu , & pCM ));
177+ if (SUCCEEDED (hr ))
178+ {
179+ HMENU hMenu = CreatePopupMenu ();
180+ hr = IContextMenu_QueryContextMenu (pCM , hMenu , 0 , first , last , CMF_NORMAL );
145181 if (SUCCEEDED (hr ))
146182 {
147- DoShellContextMenu (hwnd , pCM , File , lParam );
148- IContextMenu_Release (pCM );
183+ for (UINT i = 0 , c = GetMenuItemCount (hMenu ); i < c ; ++ i )
184+ {
185+ WCHAR buf [200 ];
186+ UINT id = GetMenuItemIdByPos (hMenu , i );
187+ if (id == (UINT )- 1 )
188+ continue ;
189+
190+ * buf = UNICODE_NULL ;
191+ hr = IContextMenu_GetCommandString (pCM , id - first , GCS_VERBW , NULL , (char * )buf , _countof (buf ));
192+ if (SUCCEEDED (hr ) && !lstrcmpiW (buf , pData -> Verb ))
193+ {
194+ PostMessageW (pData -> hwnd , WM_UPDATECOMMANDSTATE , MAKELONG (pData -> CmdId , TRUE), pData -> ImageId );
195+ break ;
196+ }
197+ }
149198 }
150- IShellFolder_Release (pSF );
199+ DestroyMenu (hMenu );
200+ IContextMenu_Release (pCM );
201+ }
202+ SHFree (pData );
203+ return 0 ;
204+ }
205+
206+ void
207+ EnableCommandIfVerbExists (UINT ImageId , HWND hwnd , UINT CmdId , PCWSTR Verb , PCWSTR File )
208+ {
209+ const SIZE_T cch = lstrlenW (File ) + 1 ;
210+ ENABLECOMMANDDATA * pData = SHAlloc (FIELD_OFFSET (ENABLECOMMANDDATA , File [cch ]));
211+ if (pData )
212+ {
213+ pData -> hwnd = hwnd ;
214+ pData -> Verb = Verb ; // Note: This assumes the string is valid for the lifetime of the thread.
215+ pData -> CmdId = CmdId ;
216+ pData -> ImageId = ImageId ;
217+ CopyMemory (pData -> File , File , cch * sizeof (* File ));
218+ SHCreateThread (EnableCommandIfVerbExistsProc , pData , CTF_COINIT | CTF_INSIST , NULL );
151219 }
152- SHFree (pidl );
153220}
154221
155- void DisplayHelp (HWND hwnd )
222+ void
223+ ShellExecuteVerb (HWND hwnd , PCWSTR Verb , PCWSTR File , BOOL Quit )
224+ {
225+ SHELLEXECUTEINFOW sei = { sizeof (sei ), SEE_MASK_INVOKEIDLIST | SEE_MASK_ASYNCOK };
226+ if (!* File )
227+ return ;
228+
229+ sei .hwnd = hwnd ;
230+ sei .lpVerb = Verb ;
231+ sei .lpFile = File ;
232+ sei .nShow = SW_SHOW ;
233+ if (!ShellExecuteExW (& sei ))
234+ {
235+ DPRINT1 ("ShellExecuteExW(%ls, %ls) failed with code %ld\n" , Verb , File , GetLastError ());
236+ }
237+ else if (Quit )
238+ {
239+ // Destroy the window to quit the application
240+ DestroyWindow (hwnd );
241+ }
242+ }
243+
244+ void
245+ DisplayHelp (HWND hwnd )
156246{
157247 SHELL_ErrorBox (hwnd , ERROR_NOT_SUPPORTED );
158248}
0 commit comments