@@ -17,6 +17,8 @@ extern "C" {
1717
1818 #include " common/windows/com.hpp"
1919
20+ #define FF_BIND_FRONT (method, pobject ) std::bind_front(&std::remove_cvref_t <decltype (*(pobject))>::method, (pobject))
21+
2022using winrt::impl::abi_t ;
2123using winrt::Windows::Foundation::IAsyncOperation;
2224using winrt::Windows::Foundation::IAsyncOperationWithProgress;
@@ -28,15 +30,15 @@ static inline void deleteHstring(HSTRING* pstr) {
2830}
2931
3032static inline void ffStrbufSetHstring (FFstrbuf* destination, HSTRING value) {
31- uint32_t length = 0 ;
33+ uint32_t length;
3234 const wchar_t * raw = WindowsGetStringRawBuffer (value, &length);
3335 ffStrbufSetNWS (destination, length, raw);
3436}
3537
3638template <typename Interface>
3739static inline HRESULT ffGetActivationFactory (const wchar_t * className, REFIID iid, Interface** factory) {
3840 HSTRING_HEADER header;
39- FF_A_CLEANUP (deleteHstring) HSTRING runtimeClass = NULL ;
41+ HSTRING runtimeClass;
4042 HRESULT hr = WindowsCreateStringReference (className, (UINT32)::wcslen (className), &header, &runtimeClass);
4143 if (FAILED (hr)) {
4244 return hr;
@@ -45,16 +47,13 @@ static inline HRESULT ffGetActivationFactory(const wchar_t* className, REFIID ii
4547 return RoGetActivationFactory (runtimeClass, iid, reinterpret_cast <void **>(factory));
4648}
4749
48- template <typename TargetProjection, typename SourceAbi, typename TargetAbi>
49- static inline HRESULT ffQueryInterface (SourceAbi* source, TargetAbi** target) {
50- *target = NULL ;
51- return reinterpret_cast <IUnknown*>(source)->QueryInterface (winrt::guid_of<TargetProjection>(), reinterpret_cast <void **>(target));
50+ template <typename TargetProjection, typename SourceAbi>
51+ static inline HRESULT ffQueryInterface (SourceAbi* source, abi_t <TargetProjection>** target) {
52+ return source->QueryInterface (winrt::guid_of<TargetProjection>(), reinterpret_cast <void **>(target));
5253}
5354
5455template <typename TOperationAbi, typename TResultAbi>
5556static HRESULT ffWaitForAsyncOperation (TOperationAbi* operation, TResultAbi** result) {
56- *result = NULL ;
57-
5857 IAsyncInfo* FF_AUTO_RELEASE_COM_OBJECT asyncInfo = NULL ;
5958 HRESULT hr = ffQueryInterface<IAsyncInfo>(operation, &asyncInfo);
6059 if (FAILED (hr)) {
@@ -84,17 +83,35 @@ static HRESULT ffWaitForAsyncOperation(TOperationAbi* operation, TResultAbi** re
8483 return operation->GetResults ((void **) result);
8584}
8685
87- static HRESULT ffSaveThumbnailToTempPath (
88- abi_t <winrt::Windows::Storage::Streams::IRandomAccessStreamReference>* thumbnail,
89- FFstrbuf* destination) {
90- abi_t <IAsyncOperation<winrt::Windows::Storage::Streams::IRandomAccessStreamWithContentType>>* FF_AUTO_RELEASE_COM_OBJECT openOperation = NULL ;
91- HRESULT hr = thumbnail->OpenReadAsync (reinterpret_cast <void **>(&openOperation));
92- if (FAILED (hr)) {
86+ template <typename TResultProjection, typename TOperation, typename ... TArgs>
87+ static HRESULT ffRunAndWait (TOperation&& operation, abi_t <TResultProjection>** result, TArgs&&... args) {
88+ abi_t <IAsyncOperation<TResultProjection>>* FF_AUTO_RELEASE_COM_OBJECT opResult = NULL ;
89+ HRESULT hr = operation (std::forward<TArgs>(args)..., reinterpret_cast <void **>(&opResult));
90+ if (FAILED (hr) || !opResult) {
91+ return hr;
92+ }
93+
94+ return ffWaitForAsyncOperation (opResult, result);
95+ }
96+
97+ template <typename TResultProjection, typename TOperation, typename ... TArgs>
98+ static HRESULT ffRunAndWait2 (TOperation&& operation, abi_t <TResultProjection>** result, TArgs&&... args) {
99+ *result = NULL ;
100+
101+ abi_t <IAsyncOperationWithProgress<TResultProjection, int32_t >>* FF_AUTO_RELEASE_COM_OBJECT opResult = NULL ;
102+ HRESULT hr = operation (std::forward<TArgs>(args)..., reinterpret_cast <void **>(&opResult));
103+ if (FAILED (hr) || !opResult) {
93104 return hr;
94105 }
95106
107+ return ffWaitForAsyncOperation (opResult, result);
108+ }
109+
110+ static HRESULT ffSaveThumbnailToTempPath (
111+ abi_t <winrt::Windows::Storage::Streams::IRandomAccessStreamReference>* thumbnail,
112+ FFstrbuf* destination) {
96113 abi_t <winrt::Windows::Storage::Streams::IRandomAccessStreamWithContentType>* FF_AUTO_RELEASE_COM_OBJECT contentStream = NULL ;
97- hr = ffWaitForAsyncOperation (openOperation , &contentStream);
114+ HRESULT hr = ffRunAndWait<winrt::Windows::Storage::Streams::IRandomAccessStreamWithContentType>( FF_BIND_FRONT (OpenReadAsync, thumbnail) , &contentStream);
98115 if (FAILED (hr) || !contentStream) {
99116 return FAILED (hr) ? hr : E_FAIL;
100117 }
@@ -133,14 +150,8 @@ static HRESULT ffSaveThumbnailToTempPath(
133150 return hr;
134151 }
135152
136- abi_t <IAsyncOperationWithProgress<winrt::Windows::Storage::Streams::IBuffer, uint32_t >>* FF_AUTO_RELEASE_COM_OBJECT readOperation = NULL ;
137- hr = inputStream->ReadAsync (buffer, (UINT32) size, static_cast <uint32_t >(winrt::Windows::Storage::Streams::InputStreamOptions::None), reinterpret_cast <void **>(&readOperation));
138- if (FAILED (hr)) {
139- return hr;
140- }
141-
142153 abi_t <winrt::Windows::Storage::Streams::IBuffer>* FF_AUTO_RELEASE_COM_OBJECT readBuffer = NULL ;
143- hr = ffWaitForAsyncOperation (readOperation, &readBuffer);
154+ ffRunAndWait2<winrt::Windows::Storage::Streams::IBuffer>( FF_BIND_FRONT (ReadAsync, inputStream), &readBuffer, buffer, (UINT32) size, static_cast < uint32_t >(winrt::Windows::Storage::Streams::InputStreamOptions::None) );
144155 if (FAILED (hr) || !readBuffer) {
145156 return FAILED (hr) ? hr : E_FAIL;
146157 }
@@ -152,7 +163,7 @@ static HRESULT ffSaveThumbnailToTempPath(
152163 }
153164
154165 Windows::Storage::Streams::IBufferByteAccess* FF_AUTO_RELEASE_COM_OBJECT byteAccess = NULL ;
155- hr = reinterpret_cast <IUnknown*>( readBuffer) ->QueryInterface (IID_PPV_ARGS (&byteAccess));
166+ hr = readBuffer->QueryInterface (IID_PPV_ARGS (&byteAccess));
156167 if (FAILED (hr)) {
157168 return hr;
158169 }
@@ -176,16 +187,18 @@ static HRESULT ffSaveThumbnailToTempPath(
176187
177188 HANDLE file = CreateFileW (tempFilePath, GENERIC_WRITE, 0 , NULL , CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
178189 if (file == INVALID_HANDLE_VALUE) {
190+ DWORD writeError = GetLastError ();
179191 DeleteFileW (tempFilePath);
180- return HRESULT_FROM_WIN32 (GetLastError () );
192+ return HRESULT_FROM_WIN32 (writeError );
181193 }
182194
183195 DWORD written = 0 ;
184196 BOOL writtenOk = WriteFile (file, bytes, length, &written, NULL );
185- DWORD writeError = writtenOk ? ERROR_SUCCESS : GetLastError ( );
186- CloseHandle ( file) ;
197+ NtClose (file );
198+ file = NULL ;
187199
188200 if (!writtenOk || written != length) {
201+ DWORD writeError = GetLastError ();
189202 DeleteFileW (tempFilePath);
190203 return HRESULT_FROM_WIN32 (writtenOk ? ERROR_WRITE_FAULT : writeError);
191204 }
@@ -212,36 +225,23 @@ static const char* getMedia(FFMediaResult* result, bool saveCover) {
212225 break ;
213226 }
214227
215- abi_t <IAsyncOperation<winrt::Windows::Media::Control::GlobalSystemMediaTransportControlsSessionManager>>* FF_AUTO_RELEASE_COM_OBJECT managerOperation = NULL ;
216- hr = managerStatics->RequestAsync (reinterpret_cast <void **>(&managerOperation));
217- if (FAILED (hr) || !managerOperation) {
218- error = " winrt: RequestAsync() failed" ;
219- break ;
220- }
221-
222228 abi_t <winrt::Windows::Media::Control::IGlobalSystemMediaTransportControlsSessionManager>* FF_AUTO_RELEASE_COM_OBJECT manager = NULL ;
223- hr = ffWaitForAsyncOperation (managerOperation , &manager);
229+ hr = ffRunAndWait<winrt::Windows::Media::Control::IGlobalSystemMediaTransportControlsSessionManager>( FF_BIND_FRONT (RequestAsync, managerStatics) , &manager);
224230 if (FAILED (hr) || !manager) {
225231 error = " winrt: RequestAsync().GetResults() failed" ;
226232 break ;
227233 }
228234
229235 abi_t <winrt::Windows::Media::Control::IGlobalSystemMediaTransportControlsSession>* FF_AUTO_RELEASE_COM_OBJECT session = NULL ;
230236 hr = manager->GetCurrentSession (reinterpret_cast <void **>(&session));
237+
231238 if (FAILED (hr) || !session) {
232239 error = " winrt: GetCurrentSession() failed" ;
233240 break ;
234241 }
235242
236- abi_t <IAsyncOperation<winrt::Windows::Media::Control::GlobalSystemMediaTransportControlsSessionMediaProperties>>* FF_AUTO_RELEASE_COM_OBJECT mediaPropsOperation = NULL ;
237- hr = session->TryGetMediaPropertiesAsync (reinterpret_cast <void **>(&mediaPropsOperation));
238- if (FAILED (hr) || !mediaPropsOperation) {
239- error = " winrt: TryGetMediaPropertiesAsync() failed" ;
240- break ;
241- }
242-
243243 abi_t <winrt::Windows::Media::Control::IGlobalSystemMediaTransportControlsSessionMediaProperties>* FF_AUTO_RELEASE_COM_OBJECT mediaProps = NULL ;
244- hr = ffWaitForAsyncOperation (mediaPropsOperation , &mediaProps);
244+ hr = ffRunAndWait<winrt::Windows::Media::Control::IGlobalSystemMediaTransportControlsSessionMediaProperties>( FF_BIND_FRONT (TryGetMediaPropertiesAsync, session) , &mediaProps);
245245 if (FAILED (hr) || !mediaProps) {
246246 error = " winrt: TryGetMediaPropertiesAsync().GetResults() failed" ;
247247 break ;
0 commit comments