#include "platformdefines.h"
-LPWSTR HackyConvertToWSTR(char* pszInput)
+LPWSTR HackyConvertToWSTR(const char* pszInput)
{
- size_t cchInput;
- LPWSTR pwszOutput;
- char* pStr;
+ size_t cchInput;
+ LPWSTR pwszOutput;
+ char* pStr;
- if (NULL == pszInput) return NULL;
+ if (NULL == pszInput) return NULL;
- // poor mans strlen
- pStr = pszInput;
- cchInput = 0;
- while('\0' != *pStr) {cchInput++; pStr++;}
- pwszOutput = new WCHAR[ cchInput + 1];
+ // poor mans strlen
+ pStr = (char*)pszInput;
+ cchInput = 0;
+ while('\0' != *pStr) {cchInput++; pStr++;}
+ pwszOutput = new WCHAR[ cchInput + 1];
- for(size_t i=0; i<=cchInput; i++)
- {
- pwszOutput[i] = (WCHAR)pszInput[i];
- }
+ for(size_t i=0; i<=cchInput; i++)
+ {
+ pwszOutput[i] = (WCHAR)pszInput[i];
+ }
- return pwszOutput;
+ return pwszOutput;
}
LPSTR HackyConvertToSTR(LPWSTR pwszInput)
{
- size_t cchInput;
- LPSTR pszOutput;
+ size_t cchInput;
+ LPSTR pszOutput;
- if (NULL == pwszInput) return NULL;
+ if (NULL == pwszInput) return NULL;
- cchInput = wcslen(pwszInput);
- pszOutput = new char[ cchInput + 1];
+ cchInput = wcslen(pwszInput);
+ pszOutput = new char[ cchInput + 1];
- for(size_t i=0; i<=cchInput; i++)
- {
- // ugly down cast
- pszOutput[i] = (char)pwszInput[i];
- }
+ for(size_t i=0; i<=cchInput; i++)
+ {
+ // ugly down cast
+ pszOutput[i] = (char)pwszInput[i];
+ }
- return pszOutput;
+ return pszOutput;
}
error_t TP_scpy_s(LPWSTR strDestination, size_t sizeInWords, LPCWSTR strSource)
{
- size_t cnt;
- // copy sizeInBytes bytes of strSource into strDestination
+ size_t cnt;
+ // copy sizeInBytes bytes of strSource into strDestination
- if (NULL == strDestination || NULL == strSource) return 1;
+ if (NULL == strDestination || NULL == strSource) return 1;
- cnt = 0;
- while(cnt < sizeInWords && '\0' != strSource[cnt])
- {
- strDestination[cnt] = strSource[cnt];
- cnt++;
- }
- strDestination[cnt] = '\0';
+ cnt = 0;
+ while(cnt < sizeInWords && '\0' != strSource[cnt])
+ {
+ strDestination[cnt] = strSource[cnt];
+ cnt++;
+ }
+ strDestination[cnt] = '\0';
- return 0;
+ return 0;
}
error_t TP_scat_s(LPWSTR strDestination, size_t sizeInWords, LPCWSTR strSource)
{
- LPWSTR strEnd;
- // locate the end (ie. '\0') and TP_scpy_s the string
+ LPWSTR strEnd;
+ // locate the end (ie. '\0') and TP_scpy_s the string
- if (NULL == strDestination || NULL == strSource) return 1;
+ if (NULL == strDestination || NULL == strSource) return 1;
- strEnd = strDestination;
- while('\0' != *strEnd) strEnd++;
+ strEnd = strDestination;
+ while('\0' != *strEnd) strEnd++;
- return TP_scpy_s(strEnd, sizeInWords - ((strEnd - strDestination) / sizeof(WCHAR)), strSource);
+ return TP_scpy_s(strEnd, sizeInWords - ((strEnd - strDestination) / sizeof(WCHAR)), strSource);
}
int TP_slen(LPWSTR str)
{
- int len;
+ int len;
- if (NULL == str) return 0;
+ if (NULL == str) return 0;
- len = 0;
- while('\0' != *(str+len)) len++;
+ len = 0;
+ while('\0' != *(str+len)) len++;
- return len;
+ return len;
}
int TP_scmp_s(LPCSTR str1, LPCSTR str2)
{
- // < 0 str1 less than str2
- // 0 str1 identical to str2
- // > 0 str1 greater than str2
+ // < 0 str1 less than str2
+ // 0 str1 identical to str2
+ // > 0 str1 greater than str2
- if (NULL == str1 && NULL != str2) return -1;
- if (NULL != str1 && NULL == str2) return 1;
- if (NULL == str1 && NULL == str2) return 0;
+ if (NULL == str1 && NULL != str2) return -1;
+ if (NULL != str1 && NULL == str2) return 1;
+ if (NULL == str1 && NULL == str2) return 0;
- while (*str1 == *str2 && '\0' != *str1 && '\0' != *str2)
- {
- str1++;
- str2++;
- }
+ while (*str1 == *str2 && '\0' != *str1 && '\0' != *str2)
+ {
+ str1++;
+ str2++;
+ }
- if ('\0' == *str1 && '\0' == *str2) return 0;
+ if ('\0' == *str1 && '\0' == *str2) return 0;
- if ('\0' != *str1) return -1;
- if ('\0' != *str2) return 1;
+ if ('\0' != *str1) return -1;
+ if ('\0' != *str2) return 1;
- return (*str1 > *str2) ? 1 : -1;
+ return (*str1 > *str2) ? 1 : -1;
}
int TP_wcmp_s(LPWSTR str1, LPWSTR str2)
{
- // < 0 str1 less than str2
- // 0 str1 identical to str2
- // > 0 str1 greater than str2
+ // < 0 str1 less than str2
+ // 0 str1 identical to str2
+ // > 0 str1 greater than str2
- if (NULL == str1 && NULL != str2) return -1;
- if (NULL != str1 && NULL == str2) return 1;
- if (NULL == str1 && NULL == str2) return 0;
+ if (NULL == str1 && NULL != str2) return -1;
+ if (NULL != str1 && NULL == str2) return 1;
+ if (NULL == str1 && NULL == str2) return 0;
- while (*str1 == *str2 && '\0' != *str1 && '\0' != *str2)
- {
- str1++;
- str2++;
- }
+ while (*str1 == *str2 && '\0' != *str1 && '\0' != *str2)
+ {
+ str1++;
+ str2++;
+ }
- if ('\0' == *str1 && '\0' == *str2) return 0;
+ if ('\0' == *str1 && '\0' == *str2) return 0;
- if ('\0' != *str1) return -1;
- if ('\0' != *str2) return 1;
+ if ('\0' != *str1) return -1;
+ if ('\0' != *str2) return 1;
- return (*str1 > *str2) ? 1 : -1;
+ return (*str1 > *str2) ? 1 : -1;
}
error_t TP_getenv_s(size_t* pReturnValue, LPWSTR buffer, size_t sizeInWords, LPCWSTR varname)
{
- if (NULL == pReturnValue || NULL == varname) return 1;
+ if (NULL == pReturnValue || NULL == varname) return 1;
#ifdef WINDOWS
-
- size_t returnValue;
+
+ size_t returnValue;
WCHAR buf[100];
if( 0 != _wgetenv_s(&returnValue, buf, 100, varname) || returnValue<=0 )
- return 2;
-
-
- TP_scpy_s(buffer, sizeInWords, (LPWSTR)buf);
+ return 2;
+
+
+ TP_scpy_s(buffer, sizeInWords, (LPWSTR)buf);
#else
- LPSTR pRet;
- pRet = getenv( HackyConvertToSTR((LPWSTR)varname) );
- if (NULL == pRet) return 2;
- TP_scpy_s(buffer, sizeInWords, HackyConvertToWSTR(pRet));
+ LPSTR pRet;
+ pRet = getenv( HackyConvertToSTR((LPWSTR)varname) );
+ if (NULL == pRet) return 2;
+ TP_scpy_s(buffer, sizeInWords, HackyConvertToWSTR(pRet));
#endif
- return 0;
+ return 0;
}
error_t TP_putenv_s(LPTSTR name, LPTSTR value)
{
- if (NULL == name || NULL == value) return 1;
+ if (NULL == name || NULL == value) return 1;
#ifdef WINDOWS
- if( 0 != _putenv_s(name, value))
- return 2;
- else
- return 0;
+ if( 0 != _putenv_s(name, value))
+ return 2;
+ else
+ return 0;
#else
- int retVal = 0;
- char *assignment = (char*) malloc(sizeof(char) * (strlen(name) + strlen(value) + 1));
- sprintf(assignment, "%s=%s", name, value);
-
- if (0 != putenv(assignment))
- retVal = 2;
- free(assignment);
- return retVal;
+ int retVal = 0;
+ char *assignment = (char*) malloc(sizeof(char) * (strlen(name) + strlen(value) + 1));
+ sprintf(assignment, "%s=%s", name, value);
+
+ if (0 != putenv(assignment))
+ retVal = 2;
+ free(assignment);
+ return retVal;
#endif
}
void TP_ZeroMemory(LPVOID buffer, size_t sizeInBytes)
{
- BYTE* bBuf;
+ BYTE* bBuf;
- // clear out the memory with 0's
- if (NULL == buffer) return;
+ // clear out the memory with 0's
+ if (NULL == buffer) return;
- bBuf = (BYTE*)buffer;
- for(size_t i=0; i<sizeInBytes; i++)
- {
- bBuf[i] = 0;
- }
+ bBuf = (BYTE*)buffer;
+ for(size_t i=0; i<sizeInBytes; i++)
+ {
+ bBuf[i] = 0;
+ }
}
error_t TP_itow_s(int num, LPWSTR buffer, size_t sizeInCharacters, int radix)
{
- size_t len;
- int tmpNum;
-
- // only support radix == 10 and only positive numbers
- if (10 != radix) return 1;
- if (0 > num) return 2;
- if (NULL == buffer) return 3;
- if (2 > sizeInCharacters) return 4;
-
- // take care of the trivial case
- if (0 == num)
- {
- buffer[0] = '\0';
- buffer[1] = '\0';
- }
-
- // get length of final string (dumb implementation)
- len = 0;
- tmpNum = num;
- while (0 < tmpNum)
- {
- tmpNum /= 10;
- len++;
- }
-
- if (len >= sizeInCharacters) return 5;
-
- // convert num into a string (backwards)
- buffer[len] = '\0';
- while(0 < num && 0 < len)
- {
+ size_t len;
+ int tmpNum;
+
+ // only support radix == 10 and only positive numbers
+ if (10 != radix) return 1;
+ if (0 > num) return 2;
+ if (NULL == buffer) return 3;
+ if (2 > sizeInCharacters) return 4;
+
+ // take care of the trivial case
+ if (0 == num)
+ {
+ buffer[0] = '\0';
+ buffer[1] = '\0';
+ }
+
+ // get length of final string (dumb implementation)
+ len = 0;
+ tmpNum = num;
+ while (0 < tmpNum)
+ {
+ tmpNum /= 10;
+ len++;
+ }
+
+ if (len >= sizeInCharacters) return 5;
+
+ // convert num into a string (backwards)
+ buffer[len] = '\0';
+ while(0 < num && 0 < len)
+ {
len--;
- buffer[len] = (WCHAR)((num % 10) + '0');
- num /= 10;
- }
+ buffer[len] = (WCHAR)((num % 10) + '0');
+ num /= 10;
+ }
- return 0;
+ return 0;
}
LPWSTR TP_sstr(LPWSTR str, LPWSTR searchStr)
{
- LPWSTR start;
- LPWSTR current;
- LPWSTR searchCurrent;
-
- if (NULL == str || NULL == searchStr) return NULL;
-
- // return a pointer to where searchStr
- // exists in str
- current = str;
- start = NULL;
- searchCurrent = searchStr;
- while('\0' != *current)
- {
- if (NULL != start && '\0' == *searchCurrent)
- {
- break;
- }
-
- if (*current == *searchCurrent)
- {
- searchCurrent++;
- if (NULL == start) start = current;
- }
- else
- {
- searchCurrent = searchStr;
- start = NULL;
- }
- current++;
- }
-
- return start;
+ LPWSTR start;
+ LPWSTR current;
+ LPWSTR searchCurrent;
+
+ if (NULL == str || NULL == searchStr) return NULL;
+
+ // return a pointer to where searchStr
+ // exists in str
+ current = str;
+ start = NULL;
+ searchCurrent = searchStr;
+ while('\0' != *current)
+ {
+ if (NULL != start && '\0' == *searchCurrent)
+ {
+ break;
+ }
+
+ if (*current == *searchCurrent)
+ {
+ searchCurrent++;
+ if (NULL == start) start = current;
+ }
+ else
+ {
+ searchCurrent = searchStr;
+ start = NULL;
+ }
+ current++;
+ }
+
+ return start;
}
DWORD TP_GetFullPathName(LPWSTR fileName, DWORD nBufferLength, LPWSTR lpBuffer)
{
#ifdef WINDOWS
- return GetFullPathNameW(fileName, nBufferLength, lpBuffer, NULL);
+ return GetFullPathNameW(fileName, nBufferLength, lpBuffer, NULL);
#else
- char nativeFullPath[MAX_PATH];
- (void)realpath(HackyConvertToSTR(fileName), nativeFullPath);
- LPWSTR fullPathForCLR = HackyConvertToWSTR(nativeFullPath);
- wcscpy_s(lpBuffer, MAX_PATH, fullPathForCLR);
- return wcslen(lpBuffer);
+ char nativeFullPath[MAX_PATH];
+ (void)realpath(HackyConvertToSTR(fileName), nativeFullPath);
+ LPWSTR fullPathForCLR = HackyConvertToWSTR(nativeFullPath);
+ wcscpy_s(lpBuffer, MAX_PATH, fullPathForCLR);
+ return wcslen(lpBuffer);
#endif
}
DWORD TP_CreateThread(THREAD_ID* tThread, LPTHREAD_START_ROUTINE worker, LPVOID lpParameter)
{
#ifdef WINDOWS
- DWORD ret;
- *tThread = CreateThread(
- NULL,
- 0,
- worker,
- lpParameter,
- 0,
- &ret);
- return ret;
+ DWORD ret;
+ *tThread = CreateThread(
+ NULL,
+ 0,
+ worker,
+ lpParameter,
+ 0,
+ &ret);
+ return ret;
#else
- pthread_create(
- tThread,
- NULL,
- (MacWorker)worker,
- lpParameter);
+ pthread_create(
+ tThread,
+ NULL,
+ (MacWorker)worker,
+ lpParameter);
#ifdef MAC64
- // This is a major kludge...64 bit posix threads just can't be cast into a DWORD and there just isn't
- // a great way to get what we're using for the ID. The fact that we're casting this at all is kind of
- // silly since we're returing the actual thread handle and everything being done to manipulate the thread
- // is done with that. Anyhow, the only thing done with the dword returned from this method is a printf
- // which is good since this DWORD really shouldn't be reliably used. Just in case it is though, return
- // a value that can be traced back to here.
- return 42;
+ // This is a major kludge...64 bit posix threads just can't be cast into a DWORD and there just isn't
+ // a great way to get what we're using for the ID. The fact that we're casting this at all is kind of
+ // silly since we're returing the actual thread handle and everything being done to manipulate the thread
+ // is done with that. Anyhow, the only thing done with the dword returned from this method is a printf
+ // which is good since this DWORD really shouldn't be reliably used. Just in case it is though, return
+ // a value that can be traced back to here.
+ return 42;
#else
- return (DWORD)*tThread;
+ return (DWORD)*tThread;
#endif
#endif
}
void TP_JoinThread(THREAD_ID tThread)
{
#ifdef WINDOWS
- WaitForSingleObject(tThread, INFINITE);
+ WaitForSingleObject(tThread, INFINITE);
#else
- pthread_join(tThread, NULL);
+ pthread_join(tThread, NULL);
#endif
}
+
+#define INTSAFE_E_ARITHMETIC_OVERFLOW ((HRESULT)0x80070216L) // 0x216 = 534 = ERROR_ARITHMETIC_OVERFLOW
+#define ULONG_ERROR (0xffffffffUL)
+#define WIN32_ALLOC_ALIGN (16 - 1)
+//
+// ULONGLONG -> ULONG conversion
+//
+HRESULT ULongLongToULong(ULONGLONG ullOperand, ULONG* pulResult)
+{
+ HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
+ *pulResult = ULONG_ERROR;
+
+ if (ullOperand <= ULONG_MAX)
+ {
+ *pulResult = (ULONG)ullOperand;
+ hr = S_OK;
+ }
+
+ return hr;
+}
+
+HRESULT ULongAdd(ULONG ulAugend, ULONG ulAddend,ULONG* pulResult)
+{
+ HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW;
+ *pulResult = ULONG_ERROR;
+
+ if ((ulAugend + ulAddend) >= ulAugend)
+ {
+ *pulResult = (ulAugend + ulAddend);
+ hr = S_OK;
+ }
+
+ return hr;
+}
+
+HRESULT ULongMult(ULONG ulMultiplicand, ULONG ulMultiplier, ULONG* pulResult)
+{
+ ULONGLONG ull64Result = UInt32x32To64(ulMultiplicand, ulMultiplier);
+
+ return ULongLongToULong(ull64Result, pulResult);
+}
+
+HRESULT CbSysStringSize(ULONG cchSize, BOOL isByteLen, ULONG *result)
+{
+ if (result == NULL)
+ return E_INVALIDARG;
+
+ // +2 for the null terminator
+ // + DWORD_PTR to store the byte length of the string
+ int constant = sizeof(WCHAR) + sizeof(DWORD_PTR) + WIN32_ALLOC_ALIGN;
+
+ if (isByteLen)
+ {
+ if (SUCCEEDED(ULongAdd(constant, cchSize, result)))
+ {
+ *result = *result & ~WIN32_ALLOC_ALIGN;
+ return S_OK;
+ }
+ }
+ else
+ {
+ ULONG temp = 0; // should not use in-place addition in ULongAdd
+ if (SUCCEEDED(ULongMult(cchSize, sizeof(WCHAR), &temp)) &
+ SUCCEEDED(ULongAdd(temp, constant, result)))
+ {
+ *result = *result & ~WIN32_ALLOC_ALIGN;
+ return S_OK;
+ }
+ }
+ return INTSAFE_E_ARITHMETIC_OVERFLOW;
+}
+
+BSTR TP_SysAllocString(LPWSTR psz)
+{
+#ifdef WINDOWS
+ return SysAllocString(psz);
+#else
+ if(psz == NULL)
+ return NULL;
+ return TP_SysAllocStringLen(psz, (DWORD)wcslen(psz));
+#endif
+}
+
+BSTR TP_SysAllocStringLen(LPWSTR psz, size_t len)
+{
+ ULONG cbTotal = 0;
+
+ if (FAILED(CbSysStringSize((ULONG)len, FALSE, &cbTotal)))
+ return NULL;
+
+ BSTR bstr = (BSTR)TP_CoTaskMemAlloc(cbTotal);
+
+ if(bstr != NULL){
+
+#if defined(_WIN64)
+ // NOTE: There are some apps which peek back 4 bytes to look at the size of the BSTR. So, in case of 64-bit code,
+ // we need to ensure that the BSTR length can be found by looking one DWORD before the BSTR pointer.
+ *(DWORD_PTR *)bstr = (DWORD_PTR) 0;
+ bstr = (BSTR) ((char *) bstr + sizeof (DWORD));
+#endif
+ *(DWORD *)bstr = (DWORD)len * sizeof(OLECHAR);
+
+ bstr = (BSTR) ((char*) bstr + sizeof(DWORD));
+
+ if(psz != NULL){
+ memcpy(bstr, psz, len * sizeof(OLECHAR));
+ }
+
+ bstr[len] = '\0'; // always 0 terminate
+ }
+
+ return bstr;
+}
+
+BSTR TP_SysAllocStringByteLen(LPCSTR psz, size_t len)
+{
+#ifdef WINDOWS
+ return SysAllocStringByteLen(psz, (UINT)len);
+#else
+ BSTR bstr;
+ ULONG cbTotal = 0;
+
+ if (FAILED(CbSysStringSize(len, TRUE, &cbTotal)))
+ return NULL;
+
+ bstr = (BSTR)TP_CoTaskMemAlloc(cbTotal);
+
+ if (bstr != NULL) {
+#if defined(_WIN64)
+ *(DWORD *)((char *)bstr + sizeof (DWORD)) = (DWORD)len;
+#else
+ *(DWORD *)bstr = (DWORD)len;
+#endif
+
+ bstr = (WCHAR*) ((char*) bstr + sizeof(DWORD_PTR));
+
+ if (psz != NULL) {
+ memcpy(bstr, psz, len);
+ }
+
+ // NULL-terminate with both a narrow and wide zero.
+ *((char *)bstr + len) = '\0';
+ *(WCHAR *)((char *)bstr + ((len + 1) & ~1)) = 0;
+ }
+
+ return bstr;
+#endif
+}
+
+void TP_SysFreeString(BSTR bstr)
+{
+#ifdef WINDOWS
+ return SysFreeString(bstr);
+#else
+ if (bstr == NULL)
+ return;
+ TP_CoTaskMemFree((BYTE *)bstr - sizeof(DWORD_PTR));
+#endif
+}
+
+size_t TP_SysStringByteLen(BSTR bstr)
+{
+#ifdef WINDOWS
+ return SysStringByteLen(bstr);
+#else
+ if(bstr == NULL)
+ return 0;
+ int32_t * p32 = (int32_t *) bstr;
+ int32_t * p32_1 = p32 -1;
+ DWORD * d32 = (DWORD *) bstr;
+ DWORD * d32_1 = d32 - 1;
+ //std::cout << p32 << p32_1 << endl;
+ //std::cout << d32 << d32_1 << endl;
+ return (unsigned int)(((DWORD *)bstr)[-1]);
+#endif
+}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <cstdint>
#ifndef _PLATFORMDEFINES__H
#define _PLATFORMDEFINES__H
#define FS_SEPERATOR L"\\"
#define PATH_DELIMITER L";"
#define L(t) L##t
-
+#define W(str) L##str
typedef unsigned error_t;
typedef HANDLE THREAD_ID;
#include <pthread.h>
typedef char16_t WCHAR;
-typedef unsigned long DWORD;
+typedef unsigned int DWORD;
typedef int BOOL;
typedef WCHAR *LPWSTR, *PWSTR;
typedef const WCHAR *LPCWSTR, *PCWSTR;
+typedef long HRESULT;
+#define LONGLONG long long
+#define ULONGLONG unsigned LONGLONG
+typedef unsigned long ULONG, *PULONG;
+#define S_OK 0x0
+#define SUCCEEDED(_hr) ((HRESULT)(_hr) >= 0)
+#define FAILED(_hr) ((HRESULT)(_hr) < 0)
+
+#ifdef ULONG_MAX
+#undef ULONG_MAX
+#endif
+#define ULONG_MAX 0xffffffffUL
+#define CCH_BSTRMAX 0x7FFFFFFF // 4 + (0x7ffffffb + 1 ) * 2 ==> 0xFFFFFFFC
+#define CB_BSTRMAX 0xFFFFFFFa // 4 + (0xfffffff6 + 2) ==> 0xFFFFFFFC
+
+#ifdef RC_INVOKED
+#define _HRESULT_TYPEDEF_(_sc) _sc
+#else // RC_INVOKED
+#define _HRESULT_TYPEDEF_(_sc) ((HRESULT)_sc)
+#endif // RC_INVOKED
+#define E_INVALIDARG _HRESULT_TYPEDEF_(0x80070057L)
+#define UInt32x32To64(a, b) ((unsigned __int64)((ULONG)(a)) * (unsigned __int64)((ULONG)(b)))
+
#ifndef TRUE
#define TRUE 1
#endif
#if __i386__
#define __stdcall __attribute__((stdcall))
#define _cdecl __attribute__((cdecl))
+#define __cdecl __attribute__((cdecl))
#else
#define __stdcall
#define _cdecl
+#define __cdecl
#endif
#endif
#define DLL_EXPORT
#endif
-LPWSTR HackyConvertToWSTR(char* pszInput);
+LPWSTR HackyConvertToWSTR(const char* pszInput);
#define FS_SEPERATOR L("/")
#define PATH_DELIMITER L(":")
#define L(t) HackyConvertToWSTR(t)
+#define W(str) u##str
#define MAX_PATH 260
typedef pthread_t THREAD_ID;
typedef WCHAR OLECHAR;
#endif
+typedef ULONG_PTR DWORD_PTR;
+
//
// Method declarations
//
void TP_DebugBreak();
DWORD TP_GetFullPathName(LPWSTR fileName, DWORD nBufferLength, LPWSTR lpBuffer);
+typedef WCHAR* BSTR;
+BSTR TP_SysAllocStringByteLen(LPSTR psz, size_t len);
+void TP_SysFreeString(BSTR bstr);
+size_t TP_SysStringByteLen(BSTR bstr);
+BSTR TP_SysAllocStringLen(LPWSTR psz, size_t len);
+BSTR TP_SysAllocString(LPWSTR psz);
+
//
// Method redirects
//
// See the LICENSE file in the project root for more information.
#include <xplatform.h>
-
+#include "platformdefines.h"
const int ARRAY_SIZE = 100;
template<typename T> bool IsObjectEquals(T o1, T o2);
list(APPEND LINK_LIBRARIES_ADDITIONAL
ole32.lib
advapi32.lib
+ OleAut32.lib
)
endif(WIN32)
add_subdirectory(StringMarshalling/LPSTR)
add_subdirectory(StringMarshalling/LPTSTR)
add_subdirectory(StringMarshalling/UTF8)
+add_subdirectory(StringMarshalling/BSTR)
add_subdirectory(MarshalAPI/FunctionPointer)
add_subdirectory(MarshalAPI/IUnknown)
add_subdirectory(SizeConst)
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.InteropServices;
+using System;
+using System.Reflection;
+using System.Text;
+using NativeDefs;
+
+class Test
+{
+
+ #region "Report Failure"
+ static int fails = 0; //record the fail numbers
+ // Overload methods for reportfailure
+ static int ReportFailure(string s)
+ {
+ Console.WriteLine(" === Fail:" + s);
+ return (++fails);
+ }
+ static int ReportFailure(string expect, string actual)
+ {
+ Console.WriteLine(" === Fail: Expected:" + expect + "\n Actual:" + actual);
+ return (++fails);
+ }
+ static int ReportFailure(string describe, string expect, string actual)
+ {
+ Console.WriteLine(" === Fail: " + describe + "\n\tExpected:" + expect + "\n\tActual:" + actual);
+ return (++fails);
+ }
+ #endregion
+
+ #region "Helper"
+ // ************************************************************
+ // Returns the appropriate exit code
+ // *************************************************************
+ static int ExitTest()
+ {
+ if (fails == 0)
+ {
+ Console.WriteLine("PASS");
+ return 100;
+ }
+ else
+ {
+ Console.WriteLine("FAIL - " + fails + " failure(s) occurred");
+ return 101;
+ }
+ }
+ #endregion
+
+ #region ReversePInvoke
+
+ public static string Call_DelMarshal_InOut(string s)
+ {
+ string strRet;
+ if (!s.Equals("\u0148"))
+ {
+ Console.WriteLine(s.Length);
+ ReportFailure("Method Call_DelMarshal_InOut[Managed Side],The passed string is wrong", "\u0148", s);
+ strRet = "\0\0\0";
+ return strRet;
+ }
+ s = "Managed";
+ strRet = "Return\0Return\0";
+ return strRet;
+ }
+
+ public static string Call_DelMarshalPointer_Out(out string s)
+ {
+ s = "Native\0String\0";
+ string strRet = "Return\0Return\0";
+ return strRet;
+ }
+
+ public static StringBuilder Call_Del_MarshalStrB_InOut(StringBuilder r)
+ {
+ StringBuilder retstr = new StringBuilder("Return\0Native");
+
+ if (!r.ToString().Equals(new StringBuilder("a", 1).ToString()))
+ {
+ ReportFailure("Method Call_Del_MarshalStrB_InOut[Managed Side] Failure. String is different than expected", "ă", r.ToString());
+ }
+ r.Replace('a', 'm');
+ return retstr;
+ }
+
+ public static StringBuilder Call_Del_MarshalStrB_Out(out StringBuilder r)
+ {
+ StringBuilder retstr = new StringBuilder("Native\0Native");
+ r = new StringBuilder("Managed", 7);
+ return retstr;
+ }
+
+ #endregion
+
+ public static int Main(string[] args)
+ {
+#pragma warning disable 0219
+ string strManaged = "Managed\0String\0";
+ string strRet = "a";
+ StringBuilder strBRet = new StringBuilder("a", 1);
+ string strNative = " Native";
+ StringBuilder strBNative = new StringBuilder(" Native", 7);
+#pragma warning restore 0219
+
+ //since the out attributes doesnt work for string, so i dont check the out value.
+ string strPara2 = strManaged;
+ string strRet2 = PInvokeDef.Marshal_InOut(strPara2);
+ if (!strRet2.Equals(strRet))
+ {
+ ReportFailure("Method PInvokeDef.Marshal_InOut[Managed Side],The Return string is wrong", strRet, strRet2);
+ }
+ if (!strPara2.Equals(strManaged))
+ {
+ ReportFailure("Method PInvokeDef.Marshal_InOut[Managed Side],The Parameter string is Changed", strManaged, strPara2);
+ }
+
+ //TestMethod3
+ string strPara3 = strManaged;
+ string strRet3 = PInvokeDef.Marshal_Out(strPara3);
+ if (!strRet.Equals(strRet3))
+ {
+ ReportFailure("Method PInvokeDef.Marshal_Out[Managed Side],The Return string is wrong", strRet, strRet3);
+ }
+ if (!strPara3.Equals(strManaged))
+ {
+ ReportFailure("Method PInvokeDef.Marshal_Out[Managed Side],The Parameter string is not Changed", strManaged, strPara3);
+ }
+
+ //TestMethod5
+ string strPara5 = strManaged;
+ string strRet5 = PInvokeDef.MarshalPointer_InOut(ref strPara5);
+
+ if (!strRet5.Equals(strRet))
+ {
+ ReportFailure("Method PInvokeDef.MarshalPointer_InOut[Managed Side],The Return string is wrong", strRet, strRet5);
+ }
+ if (!strPara5.Equals(strNative))
+ {
+ ReportFailure("Method PInvokeDef.MarshalPointer_InOut[Managed Side],The Passed string is wrong", strNative, strPara5);
+ }
+
+ //TestMethod6
+ string strPara6 = strManaged;
+ string strRet6 = PInvokeDef.MarshalPointer_Out(out strPara6);
+ if (!strRet6.Equals(strRet))
+ {
+ ReportFailure("Method PInvokeDef.MarshalPointer_Out[Managed Side],The Return string is wrong", strRet, strRet6);
+ }
+ if (!strPara6.Equals(strNative))
+ {
+ ReportFailure("Method PInvokeDef.MarshalPointer_Out[Managed Side],The Passed string is wrong", strNative, strPara6);
+ }
+
+ #region ReversePinvoke
+ DelMarshal_InOut d1 = new DelMarshal_InOut(Call_DelMarshal_InOut);
+ if (!PInvokeDef.RPinvoke_DelMarshal_InOut(d1, "\u0148"))
+ {
+ ReportFailure("Method RPinvoke_DelMarshal_InOut[Managed Side],Return value is false");
+ }
+
+ DelMarshalPointer_Out d2 = new DelMarshalPointer_Out(Call_DelMarshalPointer_Out);
+ if (!PInvokeDef.RPinvoke_DelMarshalPointer_Out(d2))
+ {
+ ReportFailure("Method RPinvoke_DelMarshal_Out[Managed Side],Return value is false");
+ }
+
+ #endregion
+ #region DelegatePInvoke
+
+ Del_Marshal_InOut d3 = new Del_Marshal_InOut(PInvokeDef.Marshal_InOut);
+ string strPara9 = strManaged;
+ string strRet9 = d3(strPara9);
+ if (!strRet9.Equals(strRet))
+ {
+ ReportFailure("Method Del_Marshal_InOut[Managed Side],The Return string is wrong", strRet, strRet9);
+ }
+ if (!strPara9.Equals(strManaged))
+ {
+ ReportFailure("Method Del_Marshal_InOut[Managed Side],The Parameter string is Changed", strManaged, strPara9);
+ }
+
+ Del_MarshalPointer_Out d4 = new Del_MarshalPointer_Out(PInvokeDef.MarshalPointer_Out);
+ string strPara10 = strManaged;
+ string strRet10 = d4(out strPara10);
+ if (!strRet10.Equals(strRet))
+ {
+ ReportFailure("Method Del_MarshalPointer_Out[Managed Side],The Return string is wrong", strRet, strRet10);
+ }
+ if (!strPara10.Equals(strNative))
+ {
+ ReportFailure("Method Del_MarshalPointer_Out[Managed Side],The Passed string is wrong", strNative, strPara10);
+ }
+
+ #endregion
+ return ExitTest();
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <AssemblyName>BSTRTest</AssemblyName>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{176EC495-7AE9-42CF-A591-06A382DB4048}</ProjectGuid>
+ <OutputType>exe</OutputType>
+ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <DefineConstants>$(DefineConstants);STATIC</DefineConstants>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+ </PropertyGroup>
+ <ItemGroup>
+ <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+ <Visible>False</Visible>
+ </CodeAnalysisDependentAssemblyPaths>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="*.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\..\Common\CoreCLRTestLibrary\CoreCLRTestLibrary.csproj">
+ <Project>{c8c0dc74-fac4-45b1-81fe-70c4808366e0}</Project>
+ <Name>CoreCLRTestLibrary</Name>
+ </ProjectReference>
+ <ProjectReference Include="CMakeLists.txt">
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#include "platformdefines.h"
+
+WCHAR strManaged[] = W("Managed\0String\0");
+size_t lenstrManaged = sizeof(strManaged) - sizeof(WCHAR);
+
+WCHAR strReturn[] = W("a\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
+WCHAR strerrReturn[] = W("error");
+
+WCHAR strNative[] = W(" Native");
+size_t lenstrNative = sizeof(strNative) - sizeof(WCHAR);
+
+//Test Method1
+extern "C" BSTR ReturnString()
+{
+ return TP_SysAllocString(strReturn);
+}
+
+extern "C" BSTR ReturnErrorString()
+{
+ return TP_SysAllocString(strerrReturn);
+}
+
+//Test Method2
+extern "C" DLL_EXPORT BSTR Marshal_InOut(/*[In,Out]*/BSTR s)
+{
+ //Check the Input
+ size_t len = TP_SysStringByteLen(s);
+
+ if (len != lenstrManaged || memcmp(s,strManaged,lenstrManaged) != 0)
+ {
+ printf("Error in Function Marshal_InOut(Native Client)\n");
+ printf("Error: Actual: %d, Expected: %d\n",(int32_t) len, (int32_t)lenstrManaged);
+
+ return ReturnErrorString();
+ }
+
+ //In-Place Change
+ memcpy(s, strNative, len);
+
+ //Return
+ return ReturnString();
+}
+
+
+extern "C" DLL_EXPORT BSTR Marshal_Out(/*[Out]*/BSTR s)
+{
+ s = TP_SysAllocString(strNative);
+
+ //Return
+ return ReturnString();
+}
+
+
+extern "C" DLL_EXPORT BSTR MarshalPointer_InOut(/*[in,out]*/BSTR *s)
+{
+ //Check the Input
+ size_t len = TP_SysStringByteLen(*s);
+
+ if (len != lenstrManaged || memcmp(*s,strManaged,lenstrManaged)!=0)
+ {
+ printf("Error in Function MarshalPointer_InOut\n");
+ printf("Error: Expected: %d, Actual: %d", (int32_t)lenstrManaged, (int32_t)len);
+
+ return ReturnErrorString();
+ }
+
+ //Allocate New
+ TP_SysFreeString(*s);
+ *s = TP_SysAllocString(strNative);
+
+ //Return
+ return ReturnString();
+}
+
+extern "C" DLL_EXPORT BSTR MarshalPointer_Out(/*[out]*/ BSTR *s)
+{
+ *s = TP_SysAllocString(strNative);
+ return ReturnString();
+}
+
+typedef BSTR (__stdcall * Test_DelMarshal_InOut)(/*[in]*/ BSTR s);
+extern "C" DLL_EXPORT BOOL __cdecl RPinvoke_DelMarshal_InOut(Test_DelMarshal_InOut d, /*[in]*/ BSTR s)
+{
+ BSTR str = d(s);
+ WCHAR ret[] = W("Return\0Return\0");
+
+ size_t lenstr = TP_SysStringByteLen(str);
+ size_t lenret = sizeof(ret) - sizeof(WCHAR);
+
+ if (lenret != lenstr || memcmp(str,ret,lenstr) != 0)
+ {
+ printf("Error in RPinvoke_DelMarshal_InOut, Returned value didn't match\n");
+ return FALSE;
+ }
+
+ TP_SysFreeString(str);
+ return TRUE;
+}
+
+//
+// PInvokeDef.cs explicitly declares that RPinvoke_DelMarshalPointer_Out uses STDCALL
+//
+typedef BSTR (__cdecl * Test_DelMarshalPointer_Out)(/*[out]*/ BSTR * s);
+extern "C" DLL_EXPORT BOOL __stdcall RPinvoke_DelMarshalPointer_Out(Test_DelMarshalPointer_Out d)
+{
+ BSTR str;
+ BSTR ret = d(&str);
+
+ WCHAR changedstr[] = W("Native\0String\0");
+
+ size_t lenstr = TP_SysStringByteLen(str);
+ size_t lenchangedstr = sizeof(changedstr) - sizeof(WCHAR);
+
+ if ( lenstr != lenchangedstr || (memcmp(str,changedstr,lenstr)!=0))
+ {
+ printf("Error in RPinvoke_DelMarshalPointer_Out, Value didn't change\n");
+ return FALSE;
+ }
+
+ WCHAR expected[] = W("Return\0Return\0");
+ size_t lenret = TP_SysStringByteLen(ret);
+ size_t lenexpected = sizeof(expected) - sizeof(WCHAR);
+
+ if (lenret != lenexpected || memcmp(ret,expected,lenret)!=0)
+ {
+ printf("Error in RPinvoke_DelMarshalPointer_Out, Return vaue is different than expected\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+//
+// PInvokeDef.cs explicitly declares that ReverseP_MarshalStrB_InOut uses STDCALL
+//
+typedef BSTR (__stdcall * Test_Del_MarshalStrB_InOut)(/*[in,out]*/ BSTR s);
+extern "C" DLL_EXPORT BOOL __stdcall ReverseP_MarshalStrB_InOut(Test_Del_MarshalStrB_InOut d, /*[in]*/ BSTR s)
+{
+ BSTR ret = d((BSTR)s);
+ WCHAR expected[] = W("Return");
+ size_t lenret = TP_SysStringByteLen(ret);
+ size_t lenexpected = sizeof(expected) - sizeof(WCHAR);
+
+ if (lenret != lenexpected || memcmp(ret,expected,lenret) != 0)
+ {
+ printf("Error in ReverseP_MarshalStrB_InOut, Return vaue is different than expected\n");
+ return FALSE;
+ }
+
+ WCHAR expectedchange[] = W("m");
+ size_t lenstr = TP_SysStringByteLen(s);
+ size_t lenexpectedchange = sizeof(expectedchange) - sizeof(WCHAR);
+
+ if (lenstr != lenexpectedchange || memcmp(s,expectedchange,lenstr) != 0)
+ {
+ printf("Error in ReverseP_MarshalStrB_InOut, Value didn't get change\n");
+ return FALSE;
+ }
+ return TRUE;
+}
--- /dev/null
+cmake_minimum_required (VERSION 2.6)
+project (BSTRTestNative)
+include_directories(${INC_PLATFORM_DIR})
+set(SOURCES BSTRTestNative.cpp)
+
+# add the executable
+add_library (BSTRTestNative SHARED ${SOURCES})
+
+if(WIN32)
+ list(APPEND LINK_LIBRARIES_ADDITIONAL
+ OleAut32.lib
+ )
+endif(WIN32)
+
+target_link_libraries(BSTRTestNative ${LINK_LIBRARIES_ADDITIONAL})
+
+# add the install targets
+install (TARGETS BSTRTestNative DESTINATION bin)
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.InteropServices;
+using System;
+using System.Reflection;
+using System.Text;
+
+namespace NativeDefs
+{
+
+ [return: MarshalAs(UnmanagedType.BStr)]
+ public delegate string Del_MarshalPointer_Out([MarshalAs(UnmanagedType.BStr)] out string s);
+
+ [return: MarshalAs(UnmanagedType.BStr)]
+ public delegate string Del_Marshal_InOut([MarshalAs(UnmanagedType.BStr)]string s);
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
+ [return: MarshalAs(UnmanagedType.BStr)]
+ public delegate string DelMarshalPointer_Out([MarshalAs(UnmanagedType.BStr)][Out] out string s);
+
+ [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode)]
+ [return: MarshalAs(UnmanagedType.BStr)]
+ public delegate string DelMarshal_InOut([MarshalAs(UnmanagedType.BStr)][In, Out]string s);
+
+ public static class PInvokeDef
+ {
+ public const string NativeBinaryName = "BSTRTestNative";
+
+ [DllImport(NativeBinaryName)]
+ [return: MarshalAs(UnmanagedType.BStr)]
+ public static extern string Marshal_InOut([In, Out][MarshalAs(UnmanagedType.BStr)]string s);
+
+ [DllImport(NativeBinaryName)]
+ [return: MarshalAs(UnmanagedType.BStr)]
+ public static extern string Marshal_Out([Out][MarshalAs(UnmanagedType.BStr)]string s);
+
+ [DllImport(NativeBinaryName)]
+ [return: MarshalAs(UnmanagedType.BStr)]
+ public static extern string MarshalPointer_InOut([MarshalAs(UnmanagedType.BStr)]ref string s);
+
+ [DllImport(NativeBinaryName)]
+ [return: MarshalAs(UnmanagedType.BStr)]
+ public static extern string MarshalPointer_Out([MarshalAs(UnmanagedType.BStr)]out string s);
+
+ [DllImport(NativeBinaryName, CallingConvention = CallingConvention.Cdecl)]
+ public static extern bool RPinvoke_DelMarshal_InOut(DelMarshal_InOut d, [MarshalAs(UnmanagedType.BStr)]string s);
+
+ [DllImport(NativeBinaryName, CallingConvention = CallingConvention.StdCall)]
+ public static extern bool RPinvoke_DelMarshalPointer_Out(DelMarshalPointer_Out d);
+ }
+}
#define INT_MIN (-2147483647 - 1)
typedef char16_t WCHAR;
-typedef unsigned long DWORD;
typedef int BOOL;
typedef WCHAR *LPWSTR, *PWSTR;
typedef const WCHAR *LPCWSTR, *PCWSTR;
typedef const char* LPCSTR;
typedef void* FARPROC;
typedef void* HMODULE;
-typedef void* ULONG_PTR;
typedef unsigned error_t;
typedef void* LPVOID;
typedef unsigned char BYTE;
typedef signed short SHORT;
typedef unsigned short WORD, *PWORD, *LPWORD;
-typedef int* DWORD_PTR;
-
#ifndef TRUE
#define TRUE 1
#endif