Skip to content
This repository was archived by the owner on Jan 28, 2022. It is now read-only.

Commit dbbe67e

Browse files
committed
Add M2CXHelpers.
1 parent a297764 commit dbbe67e

4 files changed

Lines changed: 1487 additions & 1 deletion

File tree

Lines changed: 392 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,392 @@
1+
/******************************************************************************
2+
Project: M2-Team Common Library
3+
Description: Implementation for the C++/CX helper functions.
4+
File Name: M2CXHelpers.cpp
5+
License: The MIT License
6+
******************************************************************************/
7+
8+
#include "pch.h"
9+
10+
#include <Windows.h>
11+
12+
#ifdef __cplusplus_winrt
13+
14+
#include <wrl\client.h>
15+
#include <wrl\implements.h>
16+
#include <robuffer.h>
17+
18+
#include <windows.foundation.h>
19+
#include <windows.storage.streams.h>
20+
21+
#include <string>
22+
23+
using Microsoft::WRL::ComPtr;
24+
using Microsoft::WRL::MakeAndInitialize;
25+
using Microsoft::WRL::RuntimeClass;
26+
using Microsoft::WRL::RuntimeClassFlags;
27+
using Microsoft::WRL::RuntimeClassType;
28+
29+
#include "M2CXHelpers.h"
30+
31+
// Handle the completed asynchronous call.
32+
// Parameters:
33+
// Async: The completed asynchronous call you want to handle.
34+
// Return value:
35+
// Return the HRESULT determined by the asynchronous call.
36+
HRESULT M2AsyncHandleCompleted(Platform::Object^ Async)
37+
{
38+
HRESULT hr = S_OK;
39+
ABI::Windows::Foundation::IAsyncInfo* asyncInfo = nullptr;
40+
41+
hr = M2GetInspectable(Async)->QueryInterface(&asyncInfo);
42+
if (SUCCEEDED(hr))
43+
{
44+
// Get the error code.
45+
AsyncStatus asyncStatus;
46+
hr = asyncInfo->get_Status(&asyncStatus);
47+
if (SUCCEEDED(hr))
48+
{
49+
if (AsyncStatus::Completed == asyncStatus)
50+
{
51+
// Just return S_OK if succeeded.
52+
hr = S_OK;
53+
}
54+
else if (AsyncStatus::Started == asyncStatus)
55+
{
56+
// Cancel the asynchronous call and return error code if
57+
// the status is still Started, the timeout interval has
58+
// been elapsed.
59+
hr = asyncInfo->Cancel();
60+
if (SUCCEEDED(hr)) hr = __HRESULT_FROM_WIN32(ERROR_TIMEOUT);
61+
}
62+
else if (AsyncStatus::Canceled == asyncStatus)
63+
{
64+
// If the status is Cancelled, return the error code.
65+
hr = E_ABORT;
66+
}
67+
else
68+
{
69+
HRESULT hrTemp;
70+
71+
// If the status is other value, return the error code.
72+
hr = asyncInfo->get_ErrorCode(&hrTemp);
73+
if (SUCCEEDED(hr)) hr = hrTemp;
74+
}
75+
}
76+
77+
asyncInfo->Release();
78+
}
79+
80+
return hr;
81+
}
82+
83+
// Execute function on the UI thread with normal priority.
84+
// Parameters:
85+
// agileCallback: The function you want to execute.
86+
// Return value:
87+
// The return value is Windows::Foundation::IAsyncAction^.
88+
Windows::Foundation::IAsyncAction^ M2ExecuteOnUIThread(
89+
Windows::UI::Core::DispatchedHandler^ agileCallback)
90+
{
91+
using Windows::ApplicationModel::Core::CoreApplication;
92+
using Windows::UI::Core::CoreDispatcherPriority;
93+
94+
return CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
95+
CoreDispatcherPriority::Normal, agileCallback);
96+
}
97+
98+
// Throw the appropriate Platform::Exception for the given HRESULT.
99+
// Parameters:
100+
// hr: The error HRESULT that is represented by the exception.
101+
// Return value:
102+
// This function does not return a value, but will throw Platform::Exception.
103+
__declspec(noreturn) void M2ThrowPlatformException(HRESULT hr)
104+
{
105+
throw Platform::Exception::CreateException(hr);
106+
}
107+
108+
// Throw the appropriate Platform::Exception for the given HRESULT.
109+
// Parameters:
110+
// hr: The error HRESULT that is represented by the exception.
111+
// Return value:
112+
// This function does not return a value, but will throw Platform::Exception
113+
// if it is a failed HRESULT value.
114+
void M2ThrowPlatformExceptionIfFailed(HRESULT hr)
115+
{
116+
if (FAILED(hr))
117+
{
118+
M2ThrowPlatformException(hr);
119+
}
120+
}
121+
122+
// Convert C++/CX exceptions in the callable code into HRESULTs.
123+
// Parameters:
124+
// The function does not have parameters.
125+
// Return value:
126+
// The function will return HRESULT.
127+
HRESULT M2ThrownPlatformExceptionToHResult()
128+
{
129+
try
130+
{
131+
throw;
132+
}
133+
catch (Platform::Exception^ ex)
134+
{
135+
return ex->HResult;
136+
}
137+
catch (std::bad_alloc const&)
138+
{
139+
return E_OUTOFMEMORY;
140+
}
141+
catch (...)
142+
{
143+
return E_UNEXPECTED;
144+
}
145+
}
146+
147+
// Finds a sub string from a source string.
148+
// Parameters:
149+
// SourceString: The source string.
150+
// SubString: The sub string.
151+
// IgnoreCase: Determines whether to ignore case.
152+
// Return value:
153+
// Returns true if successful, or false otherwise.
154+
bool M2FindSubString(
155+
Platform::String^ SourceString,
156+
Platform::String^ SubString,
157+
bool IgnoreCase)
158+
{
159+
return (::FindNLSStringEx(
160+
nullptr,
161+
(IgnoreCase ? NORM_IGNORECASE : 0) | FIND_FROMSTART,
162+
SourceString->Data(),
163+
SourceString->Length(),
164+
SubString->Data(),
165+
SubString->Length(),
166+
nullptr,
167+
nullptr,
168+
nullptr,
169+
0) >= 0);
170+
}
171+
172+
// Converts a numeric value into a string that represents the number expressed
173+
// as a size value in byte, bytes, kibibytes, mebibytes, gibibytes, tebibytes,
174+
// pebibytes or exbibytes, depending on the size.
175+
// Parameters:
176+
// ByteSize: The numeric byte size value to be converted.
177+
// Return value:
178+
// Returns a Platform::String object which represents the converted string.
179+
Platform::String^ M2ConvertByteSizeToString(uint64 ByteSize)
180+
{
181+
double result = static_cast<double>(ByteSize);
182+
183+
if (0.0 == result)
184+
{
185+
return L"0 Byte";
186+
}
187+
188+
const wchar_t* Systems[] =
189+
{
190+
L"Bytes",
191+
L"KiB",
192+
L"MiB",
193+
L"GiB",
194+
L"TiB",
195+
L"PiB",
196+
L"EiB"
197+
};
198+
199+
size_t nSystem = 0;
200+
for (; nSystem < sizeof(Systems) / sizeof(*Systems); ++nSystem)
201+
{
202+
if (1024.0 > result)
203+
break;
204+
205+
result /= 1024.0;
206+
}
207+
208+
Platform::String^ ByteSizeString =
209+
(static_cast<uint64>(result * 100) / 100.0).ToString();
210+
211+
return ByteSizeString + Platform::StringReference(Systems[nSystem]);
212+
}
213+
214+
// Creates a GUID, a unique 128-bit integer used for CLSIDs and interface
215+
// identifiers.
216+
// Parameters:
217+
// The function does not have parameters.
218+
// Return value:
219+
// The function will return Platform::Guid object.
220+
Platform::Guid M2CreateGuid()
221+
{
222+
GUID guid = { 0 };
223+
M2ThrowPlatformExceptionIfFailed(CoCreateGuid(&guid));
224+
return Platform::Guid(guid);
225+
}
226+
227+
// Retrieves the raw pointer from the provided IBuffer object.
228+
// Parameters:
229+
// Buffer: The IBuffer object you want to retrieve the raw pointer.
230+
// Return value:
231+
// If the function succeeds, the return value is the raw pointer from the
232+
// provided IBuffer object. If the function fails, the return value is
233+
// nullptr.
234+
// Warning:
235+
// The lifetime of the returned buffer is controlled by the lifetime of the
236+
// buffer object that's passed to this method. When the buffer has been
237+
// released, the pointer becomes invalid and must not be used.
238+
byte* M2GetPointer(Windows::Storage::Streams::IBuffer^ Buffer)
239+
{
240+
byte* pBuffer = nullptr;
241+
Windows::Storage::Streams::IBufferByteAccess* pBufferByteAccess = nullptr;
242+
IInspectable* pBufferABIObject = M2GetInspectable(Buffer);
243+
if (SUCCEEDED(pBufferABIObject->QueryInterface(&pBufferByteAccess)))
244+
{
245+
pBufferByteAccess->Buffer(&pBuffer);
246+
pBufferByteAccess->Release();
247+
}
248+
249+
return pBuffer;
250+
}
251+
252+
class BufferReference : public RuntimeClass<
253+
RuntimeClassFlags<RuntimeClassType::WinRtClassicComMix>,
254+
ABI::Windows::Storage::Streams::IBuffer,
255+
Windows::Storage::Streams::IBufferByteAccess>
256+
{
257+
private:
258+
UINT32 m_Capacity;
259+
UINT32 m_Length;
260+
byte* m_Pointer;
261+
262+
public:
263+
virtual ~BufferReference()
264+
{
265+
}
266+
267+
STDMETHODIMP RuntimeClassInitialize(
268+
byte* Pointer, UINT32 Capacity)
269+
{
270+
m_Capacity = Capacity;
271+
m_Length = Capacity;
272+
m_Pointer = Pointer;
273+
return S_OK;
274+
}
275+
276+
// IBufferByteAccess::Buffer
277+
STDMETHODIMP Buffer(byte** value)
278+
{
279+
*value = m_Pointer;
280+
return S_OK;
281+
}
282+
283+
// IBuffer::get_Capacity
284+
STDMETHODIMP get_Capacity(UINT32* value)
285+
{
286+
*value = m_Capacity;
287+
return S_OK;
288+
}
289+
290+
// IBuffer::get_Length
291+
STDMETHODIMP get_Length(UINT32* value)
292+
{
293+
*value = m_Length;
294+
return S_OK;
295+
}
296+
297+
// IBuffer::put_Length
298+
STDMETHODIMP put_Length(UINT32 value)
299+
{
300+
if (value > m_Capacity)
301+
return E_INVALIDARG;
302+
m_Length = value;
303+
return S_OK;
304+
}
305+
};
306+
307+
// Retrieves the IBuffer object from the provided raw pointer.
308+
// Parameters:
309+
// Pointer: The raw pointer you want to retrieve the IBuffer object.
310+
// Capacity: The size of raw pointer you want to retrieve the IBuffer object.
311+
// Return value:
312+
// If the function succeeds, the return value is the IBuffer object from the
313+
// provided raw pointer. If the function fails, the return value is nullptr.
314+
// Warning:
315+
// The lifetime of the returned IBuffer object is controlled by the lifetime
316+
// of the raw pointer that's passed to this method. When the raw pointer has
317+
// been released, the IBuffer object becomes invalid and must not be used.
318+
Windows::Storage::Streams::IBuffer^ M2MakeIBuffer(
319+
byte* Pointer,
320+
UINT32 Capacity)
321+
{
322+
using Windows::Storage::Streams::IBuffer;
323+
324+
IBuffer^ buffer = nullptr;
325+
326+
ComPtr<BufferReference> bufferReference;
327+
if (SUCCEEDED(MakeAndInitialize<BufferReference>(
328+
&bufferReference, Pointer, Capacity)))
329+
{
330+
buffer = reinterpret_cast<IBuffer^>(bufferReference.Get());
331+
}
332+
333+
return buffer;
334+
}
335+
336+
// Converts from the C++/CX string to the UTF-16 string.
337+
// Parameters:
338+
// PlatformString: The C++/CX string you want to convert.
339+
// Return value:
340+
// The return value is the UTF-16 string.
341+
std::wstring M2MakeUTF16String(Platform::String^ PlatformString)
342+
{
343+
return std::wstring(PlatformString->Data(), PlatformString->Length());
344+
}
345+
346+
// Converts from the C++/CX string to the UTF-8 string.
347+
// Parameters:
348+
// PlatformString: The C++/CX string you want to convert.
349+
// Return value:
350+
// The return value is the UTF-8 string.
351+
std::string M2MakeUTF8String(Platform::String^ PlatformString)
352+
{
353+
std::string UTF8String;
354+
355+
int UTF8StringLength = WideCharToMultiByte(
356+
CP_UTF8,
357+
0,
358+
PlatformString->Data(),
359+
static_cast<int>(PlatformString->Length()),
360+
nullptr,
361+
0,
362+
nullptr,
363+
nullptr);
364+
if (UTF8StringLength > 0)
365+
{
366+
UTF8String.resize(UTF8StringLength);
367+
WideCharToMultiByte(
368+
CP_UTF8,
369+
0,
370+
PlatformString->Data(),
371+
static_cast<int>(PlatformString->Length()),
372+
&UTF8String[0],
373+
UTF8StringLength,
374+
nullptr,
375+
nullptr);
376+
}
377+
378+
return UTF8String;
379+
}
380+
381+
// Converts from the UTF-8 string to the C++/CX string.
382+
// Parameters:
383+
// UTF16String: The UTF-16 string you want to convert.
384+
// Return value:
385+
// The return value is the C++/CX string.
386+
Platform::String^ M2MakeCXString(const std::wstring& UTF16String)
387+
{
388+
return ref new Platform::String(
389+
UTF16String.c_str(), static_cast<unsigned int>(UTF16String.size()));
390+
}
391+
392+
#endif // __cplusplus_winrt

0 commit comments

Comments
 (0)