commit d5d12903975c734729d1381ed4732c0c6db5ef85 Author: theonering Date: Sat Feb 20 16:30:03 2010 +0100 initial commit diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..892665b --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,19 @@ +project( SnoreNotify ) +cmake_minimum_required( VERSION 2.6 ) +set(CMAKE_BUILD_TYPE "RelWithDebInfo") +add_definitions ( -Wall ) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +find_package ( Qt4 REQUIRED ) +find_package(Automoc4 REQUIRED) + +set ( EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/build ) +set(LIBRARY_OUTPUT_PATH ${EXECUTABLE_OUTPUT_PATH}) +if(MINGW) + include_directories (${CMAKE_SOURCE_DIR}/include) + add_definitions(-D_WIN32_WINNT=0x0500) +endif(MINGW) + +option(WITH_WEBINTERFACE "Buld with WebInterface" OFF) +add_subdirectory(src) diff --git a/include/specstrings.h b/include/specstrings.h new file mode 100644 index 0000000..eb53545 --- /dev/null +++ b/include/specstrings.h @@ -0,0 +1,322 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the w64 mingw-runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#define __specstrings + +#ifdef __cplusplus +#ifndef __nothrow +#define __nothrow __declspec(nothrow) +#endif +extern "C" { +#else +#ifndef __nothrow +#define __nothrow +#endif +#endif + +#define SAL__deref_in +#define SAL__deref_in_ecount(size) +#define SAL__deref_in_bcount(size) + +#define SAL__deref_in_opt +#define SAL__deref_in_ecount_opt(size) +#define SAL__deref_in_bcount_opt(size) + +#define SAL__deref_opt_in +#define SAL__deref_opt_in_ecount(size) +#define SAL__deref_opt_in_bcount(size) + +#define SAL__deref_opt_in_opt +#define SAL__deref_opt_in_ecount_opt(size) +#define SAL__deref_opt_in_bcount_opt(size) + +#define SAL__out_awcount(expr,size) +#define SAL__in_awcount(expr,size) + +/* Renamed __null to SAL__null for avoiding private keyword conflicts between + gcc and MS world. */ +#define SAL__null +#define SAL__notnull +#define SAL__maybenull +#define SAL__readonly +#define SAL__notreadonly +#define SAL__maybereadonly +#define SAL__valid +#define SAL__notvalid +#define SAL__maybevalid +#define SAL__readableTo(extent) +#define SAL__elem_readableTo(size) +#define SAL__byte_readableTo(size) +#define SAL__writableTo(size) +#define SAL__elem_writableTo(size) +#define SAL__byte_writableTo(size) +#define SAL__deref +#define SAL__pre +#define SAL__post +#define SAL__precond(expr) +#define SAL__postcond(expr) +#define SAL__exceptthat +#define SAL__execeptthat +#define SAL__inner_success(expr) +#define SAL__inner_checkReturn +#define SAL__inner_typefix(ctype) +#define SAL__inner_override +#define SAL__inner_callback +#define SAL__inner_blocksOn(resource) +#define SAL__inner_fallthrough_dec +#define SAL__inner_fallthrough +#define __refparam +#define SAL__inner_control_entrypoint(category) +#define SAL__inner_data_entrypoint(category) + +#define SAL__ecount(size) +#define SAL__bcount(size) + +#define SAL__in +#define SAL__in_opt +#define SAL__in_nz +#define SAL__in_nz_opt +#define SAL__in_z +#define SAL__in_z_opt +#define SAL__in_ecount(size) +#define SAL__in_ecount_nz(size) +#define SAL__in_ecount_z(size) +#define SAL__in_bcount(size) +#define SAL__in_bcount_z(size) +#define SAL__in_bcount_nz(size) +#define SAL__in_ecount_opt(size) +#define SAL__in_bcount_opt(size) +#define SAL__in_ecount_z_opt(size) +#define SAL__in_bcount_z_opt(size) +#define SAL__in_ecount_nz_opt(size) +#define SAL__in_bcount_nz_opt(size) + +#define SAL__out +#define SAL__out_ecount(size) +#define SAL__out_z +#define SAL__out_nz +#define SAL__out_nz_opt +#define SAL__out_z_opt +#define SAL__out_ecount_part(size,length) +#define SAL__out_ecount_full(size) +#define SAL__out_ecount_nz(size) +#define SAL__out_ecount_z(size) +#define SAL__out_ecount_part_z(size,length) +#define SAL__out_ecount_full_z(size) +#define SAL__out_bcount(size) +#define SAL__out_bcount_part(size,length) +#define SAL__out_bcount_full(size) +#define SAL__out_bcount_z(size) +#define SAL__out_bcount_part_z(size,length) +#define SAL__out_bcount_full_z(size) +#define SAL__out_bcount_nz(size) + +#define SAL__inout +#define SAL__inout_ecount(size) +#define SAL__inout_bcount(size) +#define SAL__inout_ecount_part(size,length) +#define SAL__inout_bcount_part(size,length) +#define SAL__inout_ecount_full(size) +#define SAL__inout_bcount_full(size) +#define SAL__inout_z +#define SAL__inout_ecount_z(size) +#define SAL__inout_bcount_z(size) +#define SAL__inout_nz +#define SAL__inout_ecount_nz(size) +#define SAL__inout_bcount_nz(size) +#define SAL__ecount_opt(size) +#define SAL__bcount_opt(size) +#define SAL__out_opt +#define SAL__out_ecount_opt(size) +#define SAL__out_bcount_opt(size) +#define SAL__out_ecount_part_opt(size,length) +#define SAL__out_bcount_part_opt(size,length) +#define SAL__out_ecount_full_opt(size) +#define SAL__out_bcount_full_opt(size) +#define SAL__out_ecount_z_opt(size) +#define SAL__out_bcount_z_opt(size) +#define SAL__out_ecount_part_z_opt(size,length) +#define SAL__out_bcount_part_z_opt(size,length) +#define SAL__out_ecount_full_z_opt(size) +#define SAL__out_bcount_full_z_opt(size) +#define SAL__out_ecount_nz_opt(size) +#define SAL__out_bcount_nz_opt(size) +#define SAL__inout_opt +#define SAL__inout_ecount_opt(size) +#define SAL__inout_bcount_opt(size) +#define SAL__inout_ecount_part_opt(size,length) +#define SAL__inout_bcount_part_opt(size,length) +#define SAL__inout_ecount_full_opt(size) +#define SAL__inout_bcount_full_opt(size) +#define SAL__inout_z_opt +#define SAL__inout_ecount_z_opt(size) +#define SAL__inout_bcount_z_opt(size) +#define SAL__inout_nz_opt +#define SAL__inout_ecount_nz_opt(size) +#define SAL__inout_bcount_nz_opt(size) +#define SAL__deref_ecount(size) +#define SAL__deref_bcount(size) +#define SAL__deref_out +#define SAL__deref_out_ecount(size) +#define SAL__deref_out_bcount(size) +#define SAL__deref_out_ecount_part(size,length) +#define SAL__deref_out_bcount_part(size,length) +#define SAL__deref_out_ecount_full(size) +#define SAL__deref_out_bcount_full(size) +#define SAL__deref_out_z +#define SAL__deref_out_ecount_z(size) +#define SAL__deref_out_bcount_z(size) +#define SAL__deref_out_nz +#define SAL__deref_out_ecount_nz(size) +#define SAL__deref_out_bcount_nz(size) +#define SAL__deref_inout +#define SAL__deref_inout_ecount(size) +#define SAL__deref_inout_bcount(size) +#define SAL__deref_inout_ecount_part(size,length) +#define SAL__deref_inout_bcount_part(size,length) +#define SAL__deref_inout_ecount_full(size) +#define SAL__deref_inout_bcount_full(size) +#define SAL__deref_inout_z +#define SAL__deref_inout_ecount_z(size) +#define SAL__deref_inout_bcount_z(size) +#define SAL__deref_inout_nz +#define SAL__deref_inout_ecount_nz(size) +#define SAL__deref_inout_bcount_nz(size) +#define SAL__deref_ecount_opt(size) +#define SAL__deref_bcount_opt(size) +#define SAL__deref_out_opt +#define SAL__deref_out_ecount_opt(size) +#define SAL__deref_out_bcount_opt(size) +#define SAL__deref_out_ecount_part_opt(size,length) +#define SAL__deref_out_bcount_part_opt(size,length) +#define SAL__deref_out_ecount_full_opt(size) +#define SAL__deref_out_bcount_full_opt(size) +#define SAL__deref_out_z_opt +#define SAL__deref_out_ecount_z_opt(size) +#define SAL__deref_out_bcount_z_opt(size) +#define SAL__deref_out_nz_opt +#define SAL__deref_out_ecount_nz_opt(size) +#define SAL__deref_out_bcount_nz_opt(size) +#define SAL__deref_inout_opt +#define SAL__deref_inout_ecount_opt(size) +#define SAL__deref_inout_bcount_opt(size) +#define SAL__deref_inout_ecount_part_opt(size,length) +#define SAL__deref_inout_bcount_part_opt(size,length) +#define SAL__deref_inout_ecount_full_opt(size) +#define SAL__deref_inout_bcount_full_opt(size) +#define SAL__deref_inout_z_opt +#define SAL__deref_inout_ecount_z_opt(size) +#define SAL__deref_inout_bcount_z_opt(size) +#define SAL__deref_inout_nz_opt +#define SAL__deref_inout_ecount_nz_opt(size) +#define SAL__deref_inout_bcount_nz_opt(size) +#define SAL__deref_opt_ecount(size) +#define SAL__deref_opt_bcount(size) +#define SAL__deref_opt_out +#define SAL__deref_opt_out_z +#define SAL__deref_opt_out_ecount(size) +#define SAL__deref_opt_out_bcount(size) +#define SAL__deref_opt_out_ecount_part(size,length) +#define SAL__deref_opt_out_bcount_part(size,length) +#define SAL__deref_opt_out_ecount_full(size) +#define SAL__deref_opt_out_bcount_full(size) +#define SAL__deref_opt_inout +#define SAL__deref_opt_inout_ecount(size) +#define SAL__deref_opt_inout_bcount(size) +#define SAL__deref_opt_inout_ecount_part(size,length) +#define SAL__deref_opt_inout_bcount_part(size,length) +#define SAL__deref_opt_inout_ecount_full(size) +#define SAL__deref_opt_inout_bcount_full(size) +#define SAL__deref_opt_inout_z +#define SAL__deref_opt_inout_ecount_z(size) +#define SAL__deref_opt_inout_bcount_z(size) +#define SAL__deref_opt_inout_nz +#define SAL__deref_opt_inout_ecount_nz(size) +#define SAL__deref_opt_inout_bcount_nz(size) +#define SAL__deref_opt_ecount_opt(size) +#define SAL__deref_opt_bcount_opt(size) +#define SAL__deref_opt_out_opt +#define SAL__deref_opt_out_ecount_opt(size) +#define SAL__deref_opt_out_bcount_opt(size) +#define SAL__deref_opt_out_ecount_part_opt(size,length) +#define SAL__deref_opt_out_bcount_part_opt(size,length) +#define SAL__deref_opt_out_ecount_full_opt(size) +#define SAL__deref_opt_out_bcount_full_opt(size) +#define SAL__deref_opt_out_z_opt +#define SAL__deref_opt_out_ecount_z_opt(size) +#define SAL__deref_opt_out_bcount_z_opt(size) +#define SAL__deref_opt_out_nz_opt +#define SAL__deref_opt_out_ecount_nz_opt(size) +#define SAL__deref_opt_out_bcount_nz_opt(size) +#define SAL__deref_opt_inout_opt +#define SAL__deref_opt_inout_ecount_opt(size) +#define SAL__deref_opt_inout_bcount_opt(size) +#define SAL__deref_opt_inout_ecount_part_opt(size,length) +#define SAL__deref_opt_inout_bcount_part_opt(size,length) +#define SAL__deref_opt_inout_ecount_full_opt(size) +#define SAL__deref_opt_inout_bcount_full_opt(size) +#define SAL__deref_opt_inout_z_opt +#define SAL__deref_opt_inout_ecount_z_opt(size) +#define SAL__deref_opt_inout_bcount_z_opt(size) +#define SAL__deref_opt_inout_nz_opt +#define SAL__deref_opt_inout_ecount_nz_opt(size) +#define SAL__deref_opt_inout_bcount_nz_opt(size) + +#define SAL__success(expr) +#define SAL__nullterminated +#define SAL__nullnullterminated +#define SAL__reserved +#define SAL__checkReturn +#define SAL__typefix(ctype) +#define SAL__override +#define SAL__callback +#define SAL__format_string +#define SAL__blocksOn(resource) +#define SAL__control_entrypoint(category) +#define SAL__data_entrypoint(category) + +#ifndef __fallthrough +#define __fallthrough +#endif + +#ifndef __analysis_assume +#define __analysis_assume(expr) +#endif + +#ifndef __CLR_OR_THIS_CALL +#define __CLR_OR_THIS_CALL +#endif + +#ifndef __CLRCALL_OR_CDECL +#define __CLRCALL_OR_CDECL __cdecl +#endif + +#ifndef __STDC_WANT_SECURE_LIB__ +#define __STDC_WANT_SECURE_LIB__ 0 +#endif + +#ifndef _CRT_SECURE_NO_DEPRECATE +#define _CRT_SECURE_NO_DEPRECATE +#endif + +#ifndef RC_INVOKED +#ifndef _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES +#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 0 +#endif +#ifndef _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT +#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT 0 +#endif +#ifndef _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES +#define _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES 0 +#endif +#endif + +#ifndef DECLSPEC_ADDRSAFE +#define DECLSPEC_ADDRSAFE +#endif + +#ifdef __cplusplus +} +#endif diff --git a/include/strsafe.h b/include/strsafe.h new file mode 100644 index 0000000..6edd61c --- /dev/null +++ b/include/strsafe.h @@ -0,0 +1,2281 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the w64 mingw-runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#ifndef _STRSAFE_H_INCLUDED_ +#define _STRSAFE_H_INCLUDED_ + +#include +#include +#include +#include + +#ifndef WEOF +#define WEOF (wint_t)(0xFFFF) +#endif + +#ifndef _WCHAR_T_DEFINED +#define _WCHAR_T_DEFINED +typedef unsigned short wchar_t; +#endif + +#ifndef _HRESULT_DEFINED +#define _HRESULT_DEFINED +typedef long HRESULT; +#endif + +#ifndef SUCCEEDED +#define SUCCEEDED(hr) ((HRESULT)(hr) >= 0) +#endif + +#ifndef FAILED +#define FAILED(hr) ((HRESULT)(hr) < 0) +#endif + +#ifndef S_OK +#define S_OK ((HRESULT)0x00000000L) +#endif + +#ifndef C_ASSERT +#define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1] +#endif + +#ifdef __cplusplus +#define _STRSAFE_EXTERN_C extern "C" +#else +#define _STRSAFE_EXTERN_C extern +#endif + +#ifndef WINAPI +#define WINAPI __stdcall +#endif + +#define STRSAFEAPI static __inline HRESULT WINAPI +#define STRSAFE_INLINE_API __CRT_INLINE HRESULT WINAPI + +#define STRSAFE_MAX_CCH 2147483647 + +#ifndef _NTSTRSAFE_H_INCLUDED_ +#define STRSAFE_IGNORE_NULLS 0x00000100 +#define STRSAFE_FILL_BEHIND_NULL 0x00000200 +#define STRSAFE_FILL_ON_FAILURE 0x00000400 +#define STRSAFE_NULL_ON_FAILURE 0x00000800 +#define STRSAFE_NO_TRUNCATION 0x00001000 +#define STRSAFE_IGNORE_NULL_UNICODE_STRINGS 0x00010000 +#define STRSAFE_UNICODE_STRING_DEST_NULL_TERMINATED 0x00020000 + +#define STRSAFE_VALID_FLAGS (0x000000FF | STRSAFE_IGNORE_NULLS | STRSAFE_FILL_BEHIND_NULL | STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION) +#define STRSAFE_UNICODE_STRING_VALID_FLAGS (STRSAFE_VALID_FLAGS | STRSAFE_IGNORE_NULL_UNICODE_STRINGS | STRSAFE_UNICODE_STRING_DEST_NULL_TERMINATED) + +#define STRSAFE_FILL_BYTE(x) ((unsigned long)((x & 0x000000FF) | STRSAFE_FILL_BEHIND_NULL)) +#define STRSAFE_FAILURE_BYTE(x) ((unsigned long)((x & 0x000000FF) | STRSAFE_FILL_ON_FAILURE)) + +#define STRSAFE_GET_FILL_PATTERN(dwFlags) ((int)(dwFlags & 0x000000FF)) +#endif + +#define STRSAFE_E_INSUFFICIENT_BUFFER ((HRESULT)0x8007007AL) +#define STRSAFE_E_INVALID_PARAMETER ((HRESULT)0x80070057L) +#define STRSAFE_E_END_OF_FILE ((HRESULT)0x80070026L) + +typedef char *STRSAFE_LPSTR; +typedef const char *STRSAFE_LPCSTR; +typedef wchar_t *STRSAFE_LPWSTR; +typedef const wchar_t *STRSAFE_LPCWSTR; + +STRSAFEAPI StringCopyWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc); +STRSAFEAPI StringCopyWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc); +STRSAFEAPI StringCopyExWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags); +STRSAFEAPI StringCopyExWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags); +STRSAFEAPI StringCopyNWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,size_t cchToCopy); +STRSAFEAPI StringCopyNWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,size_t cchToCopy); +STRSAFEAPI StringCopyNExWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,size_t cchToCopy,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags); +STRSAFEAPI StringCopyNExWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,size_t cchToCopy,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags); +STRSAFEAPI StringCatWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc); +STRSAFEAPI StringCatWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc); +STRSAFEAPI StringCatExWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags); +STRSAFEAPI StringCatExWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags); +STRSAFEAPI StringCatNWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,size_t cchToAppend); +STRSAFEAPI StringCatNWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,size_t cchToAppend); +STRSAFEAPI StringCatNExWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,size_t cchToAppend,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags); +STRSAFEAPI StringCatNExWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,size_t cchToAppend,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags); +STRSAFEAPI StringVPrintfWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszFormat,va_list argList); +STRSAFEAPI StringVPrintfWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszFormat,va_list argList); +STRSAFEAPI StringVPrintfExWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags,STRSAFE_LPCSTR pszFormat,va_list argList); +STRSAFEAPI StringVPrintfExWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags,STRSAFE_LPCWSTR pszFormat,va_list argList); +STRSAFEAPI StringLengthWorkerA(STRSAFE_LPCSTR psz,size_t cchMax,size_t *pcchLength); +STRSAFEAPI StringLengthWorkerW(STRSAFE_LPCWSTR psz,size_t cchMax,size_t *pcchLength); +STRSAFE_INLINE_API StringGetsExWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags); +STRSAFE_INLINE_API StringGetsExWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags); + +#ifdef UNICODE +#define StringCchCopy StringCchCopyW +#else +#define StringCchCopy StringCchCopyA +#endif + +STRSAFEAPI StringCchCopyA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc); +STRSAFEAPI StringCchCopyW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc); + +#ifndef __CRT__NO_INLINE +STRSAFEAPI StringCchCopyA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc) { + HRESULT hr; + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = StringCopyWorkerA(pszDest,cchDest,pszSrc); + return hr; +} + +STRSAFEAPI StringCchCopyW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc) { + HRESULT hr; + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = StringCopyWorkerW(pszDest,cchDest,pszSrc); + return hr; +} +#endif /* !__CRT__NO_INLINE */ + +#ifdef UNICODE +#define StringCbCopy StringCbCopyW +#else +#define StringCbCopy StringCbCopyA +#endif + +STRSAFEAPI StringCbCopyA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc); +STRSAFEAPI StringCbCopyW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc); + +#ifndef __CRT__NO_INLINE +STRSAFEAPI StringCbCopyA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc) { + HRESULT hr; + size_t cchDest; + cchDest = cbDest / sizeof(char); + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = StringCopyWorkerA(pszDest,cchDest,pszSrc); + return hr; +} + +STRSAFEAPI StringCbCopyW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc) { + HRESULT hr; + size_t cchDest; + cchDest = cbDest / sizeof(wchar_t); + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = StringCopyWorkerW(pszDest,cchDest,pszSrc); + return hr; +} +#endif /* !__CRT__NO_INLINE */ + +#ifdef UNICODE +#define StringCchCopyEx StringCchCopyExW +#else +#define StringCchCopyEx StringCchCopyExA +#endif + +STRSAFEAPI StringCchCopyExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags); +STRSAFEAPI StringCchCopyExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags); + +#ifndef __CRT__NO_INLINE +STRSAFEAPI StringCchCopyExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags) { + HRESULT hr; + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else { + size_t cbDest; + cbDest = cchDest*sizeof(char); + hr = StringCopyExWorkerA(pszDest,cchDest,cbDest,pszSrc,ppszDestEnd,pcchRemaining,dwFlags); + } + return hr; +} + +STRSAFEAPI StringCchCopyExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags) { + HRESULT hr; + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else { + size_t cbDest; + cbDest = cchDest*sizeof(wchar_t); + hr = StringCopyExWorkerW(pszDest,cchDest,cbDest,pszSrc,ppszDestEnd,pcchRemaining,dwFlags); + } + return hr; +} +#endif /* !__CRT__NO_INLINE */ + +#ifdef UNICODE +#define StringCbCopyEx StringCbCopyExW +#else +#define StringCbCopyEx StringCbCopyExA +#endif + +STRSAFEAPI StringCbCopyExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,unsigned long dwFlags); +STRSAFEAPI StringCbCopyExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,unsigned long dwFlags); + +#ifndef __CRT__NO_INLINE +STRSAFEAPI StringCbCopyExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,unsigned long dwFlags) { + HRESULT hr; + size_t cchDest; + size_t cchRemaining = 0; + cchDest = cbDest / sizeof(char); + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = StringCopyExWorkerA(pszDest,cchDest,cbDest,pszSrc,ppszDestEnd,&cchRemaining,dwFlags); + if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER)) { + if(pcbRemaining) { + *pcbRemaining = (cchRemaining*sizeof(char)) + (cbDest % sizeof(char)); + } + } + return hr; +} + +STRSAFEAPI StringCbCopyExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,unsigned long dwFlags) { + HRESULT hr; + size_t cchDest; + size_t cchRemaining = 0; + cchDest = cbDest / sizeof(wchar_t); + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = StringCopyExWorkerW(pszDest,cchDest,cbDest,pszSrc,ppszDestEnd,&cchRemaining,dwFlags); + if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER)) { + if(pcbRemaining) { + *pcbRemaining = (cchRemaining*sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)); + } + } + return hr; +} +#endif /* !__CRT__NO_INLINE */ + +STRSAFEAPI StringCchCopyNA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,size_t cchToCopy); +STRSAFEAPI StringCchCopyNW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,size_t cchToCopy); +#ifdef UNICODE +#define StringCchCopyN StringCchCopyNW +#else +#define StringCchCopyN StringCchCopyNA +#endif + +#ifndef __CRT__NO_INLINE +STRSAFEAPI StringCchCopyNA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,size_t cchToCopy) { + HRESULT hr; + if((cchDest > STRSAFE_MAX_CCH) || (cchToCopy > STRSAFE_MAX_CCH)) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = StringCopyNWorkerA(pszDest,cchDest,pszSrc,cchToCopy); + return hr; +} + +STRSAFEAPI StringCchCopyNW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,size_t cchToCopy) { + HRESULT hr; + if((cchDest > STRSAFE_MAX_CCH) || (cchToCopy > STRSAFE_MAX_CCH)) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = StringCopyNWorkerW(pszDest,cchDest,pszSrc,cchToCopy); + return hr; +} +#endif /* !__CRT__NO_INLINE */ + +STRSAFEAPI StringCbCopyNA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,size_t cbToCopy); +STRSAFEAPI StringCbCopyNW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,size_t cbToCopy); +#ifdef UNICODE +#define StringCbCopyN StringCbCopyNW +#else +#define StringCbCopyN StringCbCopyNA +#endif + +#ifndef __CRT__NO_INLINE +STRSAFEAPI StringCbCopyNA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,size_t cbToCopy) { + HRESULT hr; + size_t cchDest; + size_t cchToCopy; + cchDest = cbDest / sizeof(char); + cchToCopy = cbToCopy / sizeof(char); + if((cchDest > STRSAFE_MAX_CCH) || (cchToCopy > STRSAFE_MAX_CCH)) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = StringCopyNWorkerA(pszDest,cchDest,pszSrc,cchToCopy); + return hr; +} + +STRSAFEAPI StringCbCopyNW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,size_t cbToCopy) { + HRESULT hr; + size_t cchDest; + size_t cchToCopy; + cchDest = cbDest / sizeof(wchar_t); + cchToCopy = cbToCopy / sizeof(wchar_t); + if((cchDest > STRSAFE_MAX_CCH) || (cchToCopy > STRSAFE_MAX_CCH)) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = StringCopyNWorkerW(pszDest,cchDest,pszSrc,cchToCopy); + return hr; +} +#endif /* !__CRT__NO_INLINE */ + +STRSAFEAPI StringCchCopyNExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,size_t cchToCopy,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags); +STRSAFEAPI StringCchCopyNExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,size_t cchToCopy,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags); +#ifdef UNICODE +#define StringCchCopyNEx StringCchCopyNExW +#else +#define StringCchCopyNEx StringCchCopyNExA +#endif + +#ifndef __CRT__NO_INLINE +STRSAFEAPI StringCchCopyNExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,size_t cchToCopy,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags) { + HRESULT hr; + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else { + size_t cbDest; + cbDest = cchDest*sizeof(char); + hr = StringCopyNExWorkerA(pszDest,cchDest,cbDest,pszSrc,cchToCopy,ppszDestEnd,pcchRemaining,dwFlags); + } + return hr; +} + +STRSAFEAPI StringCchCopyNExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,size_t cchToCopy,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags) { + HRESULT hr; + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else { + size_t cbDest; + cbDest = cchDest*sizeof(wchar_t); + hr = StringCopyNExWorkerW(pszDest,cchDest,cbDest,pszSrc,cchToCopy,ppszDestEnd,pcchRemaining,dwFlags); + } + return hr; +} +#endif /* !__CRT__NO_INLINE */ + +STRSAFEAPI StringCbCopyNExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,size_t cbToCopy,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,unsigned long dwFlags); +STRSAFEAPI StringCbCopyNExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,size_t cbToCopy,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,unsigned long dwFlags); +#ifdef UNICODE +#define StringCbCopyNEx StringCbCopyNExW +#else +#define StringCbCopyNEx StringCbCopyNExA +#endif + +#ifndef __CRT__NO_INLINE +STRSAFEAPI StringCbCopyNExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,size_t cbToCopy,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,unsigned long dwFlags) { + HRESULT hr; + size_t cchDest; + size_t cchToCopy; + size_t cchRemaining = 0; + cchDest = cbDest / sizeof(char); + cchToCopy = cbToCopy / sizeof(char); + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = StringCopyNExWorkerA(pszDest,cchDest,cbDest,pszSrc,cchToCopy,ppszDestEnd,&cchRemaining,dwFlags); + if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER)) { + if(pcbRemaining) { + *pcbRemaining = (cchRemaining*sizeof(char)) + (cbDest % sizeof(char)); + } + } + return hr; +} + +STRSAFEAPI StringCbCopyNExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,size_t cbToCopy,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,unsigned long dwFlags) { + HRESULT hr; + size_t cchDest; + size_t cchToCopy; + size_t cchRemaining = 0; + cchDest = cbDest / sizeof(wchar_t); + cchToCopy = cbToCopy / sizeof(wchar_t); + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = StringCopyNExWorkerW(pszDest,cchDest,cbDest,pszSrc,cchToCopy,ppszDestEnd,&cchRemaining,dwFlags); + if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER)) { + if(pcbRemaining) { + *pcbRemaining = (cchRemaining*sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)); + } + } + return hr; +} +#endif /* !__CRT__NO_INLINE */ + +STRSAFEAPI StringCchCatA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc); +STRSAFEAPI StringCchCatW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc); +#ifdef UNICODE +#define StringCchCat StringCchCatW +#else +#define StringCchCat StringCchCatA +#endif + +#ifndef __CRT__NO_INLINE +STRSAFEAPI StringCchCatA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc) { + HRESULT hr; + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = StringCatWorkerA(pszDest,cchDest,pszSrc); + return hr; +} + +STRSAFEAPI StringCchCatW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc) { + HRESULT hr; + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = StringCatWorkerW(pszDest,cchDest,pszSrc); + return hr; +} +#endif /* !__CRT__NO_INLINE */ + +STRSAFEAPI StringCbCatA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc); +STRSAFEAPI StringCbCatW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc); +#ifdef UNICODE +#define StringCbCat StringCbCatW +#else +#define StringCbCat StringCbCatA +#endif + +#ifndef __CRT__NO_INLINE +STRSAFEAPI StringCbCatA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc) { + HRESULT hr; + size_t cchDest; + cchDest = cbDest / sizeof(char); + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = StringCatWorkerA(pszDest,cchDest,pszSrc); + return hr; +} + +STRSAFEAPI StringCbCatW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc) { + HRESULT hr; + size_t cchDest; + cchDest = cbDest / sizeof(wchar_t); + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = StringCatWorkerW(pszDest,cchDest,pszSrc); + return hr; +} +#endif /* !__CRT__NO_INLINE */ + +STRSAFEAPI StringCchCatExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags); +STRSAFEAPI StringCchCatExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags); +#ifdef UNICODE +#define StringCchCatEx StringCchCatExW +#else +#define StringCchCatEx StringCchCatExA +#endif + +#ifndef __CRT__NO_INLINE +STRSAFEAPI StringCchCatExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags) { + HRESULT hr; + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else { + size_t cbDest; + cbDest = cchDest*sizeof(char); + hr = StringCatExWorkerA(pszDest,cchDest,cbDest,pszSrc,ppszDestEnd,pcchRemaining,dwFlags); + } + return hr; +} + +STRSAFEAPI StringCchCatExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags) { + HRESULT hr; + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else { + size_t cbDest; + cbDest = cchDest*sizeof(wchar_t); + hr = StringCatExWorkerW(pszDest,cchDest,cbDest,pszSrc,ppszDestEnd,pcchRemaining,dwFlags); + } + return hr; +} +#endif /* !__CRT__NO_INLINE */ + +STRSAFEAPI StringCbCatExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,unsigned long dwFlags); +STRSAFEAPI StringCbCatExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,unsigned long dwFlags); +#ifdef UNICODE +#define StringCbCatEx StringCbCatExW +#else +#define StringCbCatEx StringCbCatExA +#endif + +#ifndef __CRT__NO_INLINE +STRSAFEAPI StringCbCatExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,unsigned long dwFlags) { + HRESULT hr; + size_t cchDest; + size_t cchRemaining = 0; + cchDest = cbDest / sizeof(char); + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = StringCatExWorkerA(pszDest,cchDest,cbDest,pszSrc,ppszDestEnd,&cchRemaining,dwFlags); + if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER)) { + if(pcbRemaining) { + *pcbRemaining = (cchRemaining*sizeof(char)) + (cbDest % sizeof(char)); + } + } + return hr; +} + +STRSAFEAPI StringCbCatExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,unsigned long dwFlags) { + HRESULT hr; + size_t cchDest; + size_t cchRemaining = 0; + cchDest = cbDest / sizeof(wchar_t); + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = StringCatExWorkerW(pszDest,cchDest,cbDest,pszSrc,ppszDestEnd,&cchRemaining,dwFlags); + if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER)) { + if(pcbRemaining) { + *pcbRemaining = (cchRemaining*sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)); + } + } + return hr; +} +#endif /* !__CRT__NO_INLINE */ + +STRSAFEAPI StringCchCatNA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,size_t cchToAppend); +STRSAFEAPI StringCchCatNW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,size_t cchToAppend); +#ifdef UNICODE +#define StringCchCatN StringCchCatNW +#else +#define StringCchCatN StringCchCatNA +#endif + +#ifndef __CRT__NO_INLINE +STRSAFEAPI StringCchCatNA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,size_t cchToAppend) { + HRESULT hr; + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = StringCatNWorkerA(pszDest,cchDest,pszSrc,cchToAppend); + return hr; +} + +STRSAFEAPI StringCchCatNW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,size_t cchToAppend) { + HRESULT hr; + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = StringCatNWorkerW(pszDest,cchDest,pszSrc,cchToAppend); + return hr; +} +#endif /* !__CRT__NO_INLINE */ + +STRSAFEAPI StringCbCatNA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,size_t cbToAppend); +STRSAFEAPI StringCbCatNW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,size_t cbToAppend); +#ifdef UNICODE +#define StringCbCatN StringCbCatNW +#else +#define StringCbCatN StringCbCatNA +#endif + +#ifndef __CRT__NO_INLINE +STRSAFEAPI StringCbCatNA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,size_t cbToAppend) { + HRESULT hr; + size_t cchDest; + size_t cchToAppend; + cchDest = cbDest / sizeof(char); + cchToAppend = cbToAppend / sizeof(char); + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = StringCatNWorkerA(pszDest,cchDest,pszSrc,cchToAppend); + return hr; +} + +STRSAFEAPI StringCbCatNW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,size_t cbToAppend) { + HRESULT hr; + size_t cchDest; + size_t cchToAppend; + cchDest = cbDest / sizeof(wchar_t); + cchToAppend = cbToAppend / sizeof(wchar_t); + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = StringCatNWorkerW(pszDest,cchDest,pszSrc,cchToAppend); + return hr; +} +#endif /* !__CRT__NO_INLINE */ + +STRSAFEAPI StringCchCatNExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,size_t cchToAppend,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags); +STRSAFEAPI StringCchCatNExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,size_t cchToAppend,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags); +#ifdef UNICODE +#define StringCchCatNEx StringCchCatNExW +#else +#define StringCchCatNEx StringCchCatNExA +#endif + +#ifndef __CRT__NO_INLINE +STRSAFEAPI StringCchCatNExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,size_t cchToAppend,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags) { + HRESULT hr; + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else { + size_t cbDest; + cbDest = cchDest*sizeof(char); + hr = StringCatNExWorkerA(pszDest,cchDest,cbDest,pszSrc,cchToAppend,ppszDestEnd,pcchRemaining,dwFlags); + } + return hr; +} + +STRSAFEAPI StringCchCatNExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,size_t cchToAppend,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags) { + HRESULT hr; + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else { + size_t cbDest; + cbDest = cchDest*sizeof(wchar_t); + hr = StringCatNExWorkerW(pszDest,cchDest,cbDest,pszSrc,cchToAppend,ppszDestEnd,pcchRemaining,dwFlags); + } + return hr; +} +#endif + +STRSAFEAPI StringCbCatNExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,size_t cbToAppend,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,unsigned long dwFlags); +STRSAFEAPI StringCbCatNExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,size_t cbToAppend,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,unsigned long dwFlags); +#ifdef UNICODE +#define StringCbCatNEx StringCbCatNExW +#else +#define StringCbCatNEx StringCbCatNExA +#endif + +#ifndef __CRT__NO_INLINE +STRSAFEAPI StringCbCatNExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,size_t cbToAppend,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,unsigned long dwFlags) { + HRESULT hr; + size_t cchDest; + size_t cchToAppend; + size_t cchRemaining = 0; + cchDest = cbDest / sizeof(char); + cchToAppend = cbToAppend / sizeof(char); + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = StringCatNExWorkerA(pszDest,cchDest,cbDest,pszSrc,cchToAppend,ppszDestEnd,&cchRemaining,dwFlags); + if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER)) { + if(pcbRemaining) { + *pcbRemaining = (cchRemaining*sizeof(char)) + (cbDest % sizeof(char)); + } + } + return hr; +} + +STRSAFEAPI StringCbCatNExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,size_t cbToAppend,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,unsigned long dwFlags) { + HRESULT hr; + size_t cchDest; + size_t cchToAppend; + size_t cchRemaining = 0; + cchDest = cbDest / sizeof(wchar_t); + cchToAppend = cbToAppend / sizeof(wchar_t); + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = StringCatNExWorkerW(pszDest,cchDest,cbDest,pszSrc,cchToAppend,ppszDestEnd,&cchRemaining,dwFlags); + if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER)) { + if(pcbRemaining) { + *pcbRemaining = (cchRemaining*sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)); + } + } + return hr; +} +#endif /* !__CRT__NO_INLINE */ + +STRSAFEAPI StringCchVPrintfA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszFormat,va_list argList); +STRSAFEAPI StringCchVPrintfW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszFormat,va_list argList); +#ifdef UNICODE +#define StringCchVPrintf StringCchVPrintfW +#else +#define StringCchVPrintf StringCchVPrintfA +#endif + +#ifndef __CRT__NO_INLINE +STRSAFEAPI StringCchVPrintfA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszFormat,va_list argList) { + HRESULT hr; + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = StringVPrintfWorkerA(pszDest,cchDest,pszFormat,argList); + return hr; +} + +STRSAFEAPI StringCchVPrintfW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszFormat,va_list argList) { + HRESULT hr; + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = StringVPrintfWorkerW(pszDest,cchDest,pszFormat,argList); + return hr; +} +#endif /* !__CRT__NO_INLINE */ + +STRSAFEAPI StringCbVPrintfA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszFormat,va_list argList); +STRSAFEAPI StringCbVPrintfW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszFormat,va_list argList); +#ifdef UNICODE +#define StringCbVPrintf StringCbVPrintfW +#else +#define StringCbVPrintf StringCbVPrintfA +#endif + +#ifndef __CRT__NO_INLINE +STRSAFEAPI StringCbVPrintfA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszFormat,va_list argList) { + HRESULT hr; + size_t cchDest; + cchDest = cbDest / sizeof(char); + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = StringVPrintfWorkerA(pszDest,cchDest,pszFormat,argList); + return hr; +} + +STRSAFEAPI StringCbVPrintfW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszFormat,va_list argList) { + HRESULT hr; + size_t cchDest; + cchDest = cbDest / sizeof(wchar_t); + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = StringVPrintfWorkerW(pszDest,cchDest,pszFormat,argList); + return hr; +} +#endif /* !__CRT__NO_INLINE */ + +STRSAFEAPI StringCchPrintfA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszFormat,...); +STRSAFEAPI StringCchPrintfW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszFormat,...); +#ifdef UNICODE +#define StringCchPrintf StringCchPrintfW +#else +#define StringCchPrintf StringCchPrintfA +#endif + +#ifndef __CRT__NO_INLINE +STRSAFEAPI StringCchPrintfA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszFormat,...) { + HRESULT hr; + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else { + va_list argList; + va_start(argList,pszFormat); + hr = StringVPrintfWorkerA(pszDest,cchDest,pszFormat,argList); + va_end(argList); + } + return hr; +} + +STRSAFEAPI StringCchPrintfW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszFormat,...) { + HRESULT hr; + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else { + va_list argList; + va_start(argList,pszFormat); + hr = StringVPrintfWorkerW(pszDest,cchDest,pszFormat,argList); + va_end(argList); + } + return hr; +} +#endif /* !__CRT__NO_INLINE */ + +STRSAFEAPI StringCbPrintfA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszFormat,...); +STRSAFEAPI StringCbPrintfW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszFormat,...); +#ifdef UNICODE +#define StringCbPrintf StringCbPrintfW +#else +#define StringCbPrintf StringCbPrintfA +#endif + +#ifndef __CRT__NO_INLINE +STRSAFEAPI StringCbPrintfA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszFormat,...) { + HRESULT hr; + size_t cchDest; + cchDest = cbDest / sizeof(char); + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else { + va_list argList; + va_start(argList,pszFormat); + hr = StringVPrintfWorkerA(pszDest,cchDest,pszFormat,argList); + va_end(argList); + } + return hr; +} + +STRSAFEAPI StringCbPrintfW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszFormat,...) { + HRESULT hr; + size_t cchDest; + cchDest = cbDest / sizeof(wchar_t); + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else { + va_list argList; + va_start(argList,pszFormat); + hr = StringVPrintfWorkerW(pszDest,cchDest,pszFormat,argList); + va_end(argList); + } + return hr; +} +#endif /* !__CRT__NO_INLINE */ + +STRSAFEAPI StringCchPrintfExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags,STRSAFE_LPCSTR pszFormat,...); +STRSAFEAPI StringCchPrintfExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags,STRSAFE_LPCWSTR pszFormat,...); +#ifdef UNICODE +#define StringCchPrintfEx StringCchPrintfExW +#else +#define StringCchPrintfEx StringCchPrintfExA +#endif + +#ifndef __CRT__NO_INLINE +STRSAFEAPI StringCchPrintfExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags,STRSAFE_LPCSTR pszFormat,...) { + HRESULT hr; + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else { + size_t cbDest; + va_list argList; + cbDest = cchDest*sizeof(char); + va_start(argList,pszFormat); + hr = StringVPrintfExWorkerA(pszDest,cchDest,cbDest,ppszDestEnd,pcchRemaining,dwFlags,pszFormat,argList); + va_end(argList); + } + return hr; +} + +STRSAFEAPI StringCchPrintfExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags,STRSAFE_LPCWSTR pszFormat,...) { + HRESULT hr; + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else { + size_t cbDest; + va_list argList; + cbDest = cchDest*sizeof(wchar_t); + va_start(argList,pszFormat); + hr = StringVPrintfExWorkerW(pszDest,cchDest,cbDest,ppszDestEnd,pcchRemaining,dwFlags,pszFormat,argList); + va_end(argList); + } + return hr; +} +#endif /* !__CRT__NO_INLINE */ + +STRSAFEAPI StringCbPrintfExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,unsigned long dwFlags,STRSAFE_LPCSTR pszFormat,...); +STRSAFEAPI StringCbPrintfExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,unsigned long dwFlags,STRSAFE_LPCWSTR pszFormat,...); +#ifdef UNICODE +#define StringCbPrintfEx StringCbPrintfExW +#else +#define StringCbPrintfEx StringCbPrintfExA +#endif + +#ifndef __CRT__NO_INLINE +STRSAFEAPI StringCbPrintfExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,unsigned long dwFlags,STRSAFE_LPCSTR pszFormat,...) { + HRESULT hr; + size_t cchDest; + size_t cchRemaining = 0; + cchDest = cbDest / sizeof(char); + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else { + va_list argList; + va_start(argList,pszFormat); + hr = StringVPrintfExWorkerA(pszDest,cchDest,cbDest,ppszDestEnd,&cchRemaining,dwFlags,pszFormat,argList); + va_end(argList); + } + if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER)) { + if(pcbRemaining) { + *pcbRemaining = (cchRemaining*sizeof(char)) + (cbDest % sizeof(char)); + } + } + return hr; +} + +STRSAFEAPI StringCbPrintfExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,unsigned long dwFlags,STRSAFE_LPCWSTR pszFormat,...) { + HRESULT hr; + size_t cchDest; + size_t cchRemaining = 0; + cchDest = cbDest / sizeof(wchar_t); + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else { + va_list argList; + va_start(argList,pszFormat); + hr = StringVPrintfExWorkerW(pszDest,cchDest,cbDest,ppszDestEnd,&cchRemaining,dwFlags,pszFormat,argList); + va_end(argList); + } + if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER)) { + if(pcbRemaining) { + *pcbRemaining = (cchRemaining*sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)); + } + } + return hr; +} +#endif /* !__CRT__NO_INLINE */ + +STRSAFEAPI StringCchVPrintfExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags,STRSAFE_LPCSTR pszFormat,va_list argList); +STRSAFEAPI StringCchVPrintfExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags,STRSAFE_LPCWSTR pszFormat,va_list argList); +#ifdef UNICODE +#define StringCchVPrintfEx StringCchVPrintfExW +#else +#define StringCchVPrintfEx StringCchVPrintfExA +#endif + +#ifndef __CRT__NO_INLINE +STRSAFEAPI StringCchVPrintfExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags,STRSAFE_LPCSTR pszFormat,va_list argList) { + HRESULT hr; + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else { + size_t cbDest; + cbDest = cchDest*sizeof(char); + hr = StringVPrintfExWorkerA(pszDest,cchDest,cbDest,ppszDestEnd,pcchRemaining,dwFlags,pszFormat,argList); + } + return hr; +} + +STRSAFEAPI StringCchVPrintfExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags,STRSAFE_LPCWSTR pszFormat,va_list argList) { + HRESULT hr; + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else { + size_t cbDest; + cbDest = cchDest*sizeof(wchar_t); + hr = StringVPrintfExWorkerW(pszDest,cchDest,cbDest,ppszDestEnd,pcchRemaining,dwFlags,pszFormat,argList); + } + return hr; +} +#endif /* !__CRT__NO_INLINE */ + +STRSAFEAPI StringCbVPrintfExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,unsigned long dwFlags,STRSAFE_LPCSTR pszFormat,va_list argList); +STRSAFEAPI StringCbVPrintfExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,unsigned long dwFlags,STRSAFE_LPCWSTR pszFormat,va_list argList); +#ifdef UNICODE +#define StringCbVPrintfEx StringCbVPrintfExW +#else +#define StringCbVPrintfEx StringCbVPrintfExA +#endif + +#ifndef __CRT__NO_INLINE +STRSAFEAPI StringCbVPrintfExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,unsigned long dwFlags,STRSAFE_LPCSTR pszFormat,va_list argList) { + HRESULT hr; + size_t cchDest; + size_t cchRemaining = 0; + cchDest = cbDest / sizeof(char); + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = StringVPrintfExWorkerA(pszDest,cchDest,cbDest,ppszDestEnd,&cchRemaining,dwFlags,pszFormat,argList); + if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER)) { + if(pcbRemaining) { + *pcbRemaining = (cchRemaining*sizeof(char)) + (cbDest % sizeof(char)); + } + } + return hr; +} + +STRSAFEAPI StringCbVPrintfExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,unsigned long dwFlags,STRSAFE_LPCWSTR pszFormat,va_list argList) { + HRESULT hr; + size_t cchDest; + size_t cchRemaining = 0; + cchDest = cbDest / sizeof(wchar_t); + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = StringVPrintfExWorkerW(pszDest,cchDest,cbDest,ppszDestEnd,&cchRemaining,dwFlags,pszFormat,argList); + if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER)) { + if(pcbRemaining) { + *pcbRemaining = (cchRemaining*sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)); + } + } + return hr; +} +#endif /* !__CRT__NO_INLINE */ + +STRSAFE_INLINE_API StringCchGetsA(STRSAFE_LPSTR pszDest,size_t cchDest); +STRSAFE_INLINE_API StringCchGetsW(STRSAFE_LPWSTR pszDest,size_t cchDest); +#ifdef UNICODE +#define StringCchGets StringCchGetsW +#else +#define StringCchGets StringCchGetsA +#endif + +#ifndef __CRT__NO_INLINE +STRSAFE_INLINE_API StringCchGetsA(STRSAFE_LPSTR pszDest,size_t cchDest) { + HRESULT hr; + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else { + size_t cbDest; + cbDest = cchDest*sizeof(char); + hr = StringGetsExWorkerA(pszDest,cchDest,cbDest,NULL,NULL,0); + } + return hr; +} + +STRSAFE_INLINE_API StringCchGetsW(STRSAFE_LPWSTR pszDest,size_t cchDest) { + HRESULT hr; + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else { + size_t cbDest; + cbDest = cchDest*sizeof(wchar_t); + hr = StringGetsExWorkerW(pszDest,cchDest,cbDest,NULL,NULL,0); + } + return hr; +} +#endif /* !__CRT__NO_INLINE */ + +STRSAFE_INLINE_API StringCbGetsA(STRSAFE_LPSTR pszDest,size_t cbDest); +STRSAFE_INLINE_API StringCbGetsW(STRSAFE_LPWSTR pszDest,size_t cbDest); +#ifdef UNICODE +#define StringCbGets StringCbGetsW +#else +#define StringCbGets StringCbGetsA +#endif + +#ifndef __CRT__NO_INLINE +STRSAFE_INLINE_API StringCbGetsA(STRSAFE_LPSTR pszDest,size_t cbDest) { + HRESULT hr; + size_t cchDest; + cchDest = cbDest / sizeof(char); + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = StringGetsExWorkerA(pszDest,cchDest,cbDest,NULL,NULL,0); + return hr; +} + +STRSAFE_INLINE_API StringCbGetsW(STRSAFE_LPWSTR pszDest,size_t cbDest) { + HRESULT hr; + size_t cchDest; + cchDest = cbDest / sizeof(wchar_t); + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = StringGetsExWorkerW(pszDest,cchDest,cbDest,NULL,NULL,0); + return hr; +} +#endif /* !__CRT__NO_INLINE */ + +STRSAFE_INLINE_API StringCchGetsExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags); +STRSAFE_INLINE_API StringCchGetsExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags); +#ifdef UNICODE +#define StringCchGetsEx StringCchGetsExW +#else +#define StringCchGetsEx StringCchGetsExA +#endif + +#ifndef __CRT__NO_INLINE +STRSAFE_INLINE_API StringCchGetsExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags) { + HRESULT hr; + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else { + size_t cbDest; + cbDest = cchDest*sizeof(char); + hr = StringGetsExWorkerA(pszDest,cchDest,cbDest,ppszDestEnd,pcchRemaining,dwFlags); + } + return hr; +} + +STRSAFE_INLINE_API StringCchGetsExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags) { + HRESULT hr; + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else { + size_t cbDest; + cbDest = cchDest*sizeof(wchar_t); + hr = StringGetsExWorkerW(pszDest,cchDest,cbDest,ppszDestEnd,pcchRemaining,dwFlags); + } + return hr; +} +#endif /* !__CRT__NO_INLINE */ + +STRSAFE_INLINE_API StringCbGetsExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,unsigned long dwFlags); +STRSAFE_INLINE_API StringCbGetsExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,unsigned long dwFlags); +#ifdef UNICODE +#define StringCbGetsEx StringCbGetsExW +#else +#define StringCbGetsEx StringCbGetsExA +#endif + +#ifndef __CRT__NO_INLINE +STRSAFE_INLINE_API StringCbGetsExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,unsigned long dwFlags) { + HRESULT hr; + size_t cchDest; + size_t cchRemaining = 0; + cchDest = cbDest / sizeof(char); + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = StringGetsExWorkerA(pszDest,cchDest,cbDest,ppszDestEnd,&cchRemaining,dwFlags); + if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER) || (hr==STRSAFE_E_END_OF_FILE)) { + if(pcbRemaining) *pcbRemaining = (cchRemaining*sizeof(char)) + (cbDest % sizeof(char)); + } + return hr; +} + +STRSAFE_INLINE_API StringCbGetsExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,unsigned long dwFlags) { + HRESULT hr; + size_t cchDest; + size_t cchRemaining = 0; + cchDest = cbDest / sizeof(wchar_t); + if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = StringGetsExWorkerW(pszDest,cchDest,cbDest,ppszDestEnd,&cchRemaining,dwFlags); + if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER) || (hr==STRSAFE_E_END_OF_FILE)) { + if(pcbRemaining) *pcbRemaining = (cchRemaining*sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)); + } + return hr; +} +#endif /* !__CRT__NO_INLINE */ + +STRSAFEAPI StringCchLengthA(STRSAFE_LPCSTR psz,size_t cchMax,size_t *pcchLength); +STRSAFEAPI StringCchLengthW(STRSAFE_LPCWSTR psz,size_t cchMax,size_t *pcchLength); +#ifdef UNICODE +#define StringCchLength StringCchLengthW +#else +#define StringCchLength StringCchLengthA +#endif + +#ifndef __CRT__NO_INLINE +STRSAFEAPI StringCchLengthA(STRSAFE_LPCSTR psz,size_t cchMax,size_t *pcchLength) { + HRESULT hr; + if(!psz || (cchMax > STRSAFE_MAX_CCH)) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = StringLengthWorkerA(psz,cchMax,pcchLength); + if(FAILED(hr) && pcchLength) { + *pcchLength = 0; + } + return hr; +} + +STRSAFEAPI StringCchLengthW(STRSAFE_LPCWSTR psz,size_t cchMax,size_t *pcchLength) { + HRESULT hr; + if(!psz || (cchMax > STRSAFE_MAX_CCH)) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = StringLengthWorkerW(psz,cchMax,pcchLength); + if(FAILED(hr) && pcchLength) { + *pcchLength = 0; + } + return hr; +} +#endif /* !__CRT__NO_INLINE */ + +STRSAFEAPI StringCbLengthA(STRSAFE_LPCSTR psz,size_t cbMax,size_t *pcbLength); +STRSAFEAPI StringCbLengthW(STRSAFE_LPCWSTR psz,size_t cbMax,size_t *pcbLength); +#ifdef UNICODE +#define StringCbLength StringCbLengthW +#else +#define StringCbLength StringCbLengthA +#endif + +#ifndef __CRT__NO_INLINE +STRSAFEAPI StringCbLengthA(STRSAFE_LPCSTR psz,size_t cbMax,size_t *pcbLength) { + HRESULT hr; + size_t cchMax; + size_t cchLength = 0; + cchMax = cbMax / sizeof(char); + if(!psz || (cchMax > STRSAFE_MAX_CCH)) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = StringLengthWorkerA(psz,cchMax,&cchLength); + if(pcbLength) { + if(SUCCEEDED(hr)) { + *pcbLength = cchLength*sizeof(char); + } else { + *pcbLength = 0; + } + } + return hr; +} + +STRSAFEAPI StringCbLengthW(STRSAFE_LPCWSTR psz,size_t cbMax,size_t *pcbLength) { + HRESULT hr; + size_t cchMax; + size_t cchLength = 0; + cchMax = cbMax / sizeof(wchar_t); + if(!psz || (cchMax > STRSAFE_MAX_CCH)) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = StringLengthWorkerW(psz,cchMax,&cchLength); + if(pcbLength) { + if(SUCCEEDED(hr)) { + *pcbLength = cchLength*sizeof(wchar_t); + } else { + *pcbLength = 0; + } + } + return hr; +} + +STRSAFEAPI StringCopyWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc) { + HRESULT hr = S_OK; + if(cchDest==0) hr = STRSAFE_E_INVALID_PARAMETER; + else { + while(cchDest && (*pszSrc!='\0')) { + *pszDest++ = *pszSrc++; + cchDest--; + } + if(cchDest==0) { + pszDest--; + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + *pszDest= '\0'; + } + return hr; +} + +STRSAFEAPI StringCopyWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc) { + HRESULT hr = S_OK; + if(cchDest==0) hr = STRSAFE_E_INVALID_PARAMETER; + else { + while(cchDest && (*pszSrc!=L'\0')) { + *pszDest++ = *pszSrc++; + cchDest--; + } + if(cchDest==0) { + pszDest--; + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + *pszDest= L'\0'; + } + return hr; +} + +STRSAFEAPI StringCopyExWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags) { + HRESULT hr = S_OK; + STRSAFE_LPSTR pszDestEnd = pszDest; + size_t cchRemaining = 0; + if(dwFlags & (~STRSAFE_VALID_FLAGS)) hr = STRSAFE_E_INVALID_PARAMETER; + else { + if(dwFlags & STRSAFE_IGNORE_NULLS) { + if(!pszDest) { + if((cchDest!=0) || (cbDest!=0)) hr = STRSAFE_E_INVALID_PARAMETER; + } + if(!pszSrc) pszSrc = ""; + } + if(SUCCEEDED(hr)) { + if(cchDest==0) { + pszDestEnd = pszDest; + cchRemaining = 0; + if(*pszSrc!='\0') { + if(!pszDest) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + } else { + pszDestEnd = pszDest; + cchRemaining = cchDest; + while(cchRemaining && (*pszSrc!='\0')) { + *pszDestEnd++ = *pszSrc++; + cchRemaining--; + } + if(cchRemaining > 0) { + if(dwFlags & STRSAFE_FILL_BEHIND_NULL) { + memset(pszDestEnd + 1,STRSAFE_GET_FILL_PATTERN(dwFlags),((cchRemaining - 1)*sizeof(char)) + (cbDest % sizeof(char))); + } + } else { + pszDestEnd--; + cchRemaining++; + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + *pszDestEnd = '\0'; + } + } + } + if(FAILED(hr)) { + if(pszDest) { + if(dwFlags & STRSAFE_FILL_ON_FAILURE) { + memset(pszDest,STRSAFE_GET_FILL_PATTERN(dwFlags),cbDest); + if(STRSAFE_GET_FILL_PATTERN(dwFlags)==0) { + pszDestEnd = pszDest; + cchRemaining = cchDest; + } else if(cchDest > 0) { + pszDestEnd = pszDest + cchDest - 1; + cchRemaining = 1; + *pszDestEnd = '\0'; + } + } + if(dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) { + if(cchDest > 0) { + pszDestEnd = pszDest; + cchRemaining = cchDest; + *pszDestEnd = '\0'; + } + } + } + } + if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER)) { + if(ppszDestEnd) *ppszDestEnd = pszDestEnd; + if(pcchRemaining) *pcchRemaining = cchRemaining; + } + return hr; +} + +STRSAFEAPI StringCopyExWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags) { + HRESULT hr = S_OK; + STRSAFE_LPWSTR pszDestEnd = pszDest; + size_t cchRemaining = 0; + if(dwFlags & (~STRSAFE_VALID_FLAGS)) hr = STRSAFE_E_INVALID_PARAMETER; + else { + if(dwFlags & STRSAFE_IGNORE_NULLS) { + if(!pszDest) { + if((cchDest!=0) || (cbDest!=0)) hr = STRSAFE_E_INVALID_PARAMETER; + } + if(!pszSrc) pszSrc = L""; + } + if(SUCCEEDED(hr)) { + if(cchDest==0) { + pszDestEnd = pszDest; + cchRemaining = 0; + if(*pszSrc!=L'\0') { + if(!pszDest) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + } else { + pszDestEnd = pszDest; + cchRemaining = cchDest; + while(cchRemaining && (*pszSrc!=L'\0')) { + *pszDestEnd++ = *pszSrc++; + cchRemaining--; + } + if(cchRemaining > 0) { + if(dwFlags & STRSAFE_FILL_BEHIND_NULL) { + memset(pszDestEnd + 1,STRSAFE_GET_FILL_PATTERN(dwFlags),((cchRemaining - 1)*sizeof(wchar_t)) + (cbDest % sizeof(wchar_t))); + } + } else { + pszDestEnd--; + cchRemaining++; + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + *pszDestEnd = L'\0'; + } + } + } + if(FAILED(hr)) { + if(pszDest) { + if(dwFlags & STRSAFE_FILL_ON_FAILURE) { + memset(pszDest,STRSAFE_GET_FILL_PATTERN(dwFlags),cbDest); + if(STRSAFE_GET_FILL_PATTERN(dwFlags)==0) { + pszDestEnd = pszDest; + cchRemaining = cchDest; + } else if(cchDest > 0) { + pszDestEnd = pszDest + cchDest - 1; + cchRemaining = 1; + *pszDestEnd = L'\0'; + } + } + if(dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) { + if(cchDest > 0) { + pszDestEnd = pszDest; + cchRemaining = cchDest; + *pszDestEnd = L'\0'; + } + } + } + } + if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER)) { + if(ppszDestEnd) *ppszDestEnd = pszDestEnd; + if(pcchRemaining) *pcchRemaining = cchRemaining; + } + return hr; +} + +STRSAFEAPI StringCopyNWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,size_t cchSrc) { + HRESULT hr = S_OK; + if(cchDest==0) hr = STRSAFE_E_INVALID_PARAMETER; + else { + while(cchDest && cchSrc && (*pszSrc!='\0')) { + *pszDest++ = *pszSrc++; + cchDest--; + cchSrc--; + } + if(cchDest==0) { + pszDest--; + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + *pszDest= '\0'; + } + return hr; +} + +STRSAFEAPI StringCopyNWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,size_t cchToCopy) { + HRESULT hr = S_OK; + if(cchDest==0) hr = STRSAFE_E_INVALID_PARAMETER; + else { + while(cchDest && cchToCopy && (*pszSrc!=L'\0')) { + *pszDest++ = *pszSrc++; + cchDest--; + cchToCopy--; + } + if(cchDest==0) { + pszDest--; + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + *pszDest= L'\0'; + } + return hr; +} + +STRSAFEAPI StringCopyNExWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,size_t cchToCopy,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags) { + HRESULT hr = S_OK; + STRSAFE_LPSTR pszDestEnd = pszDest; + size_t cchRemaining = 0; + if(dwFlags & (~STRSAFE_VALID_FLAGS)) hr = STRSAFE_E_INVALID_PARAMETER; + else if(cchToCopy > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else { + if(dwFlags & STRSAFE_IGNORE_NULLS) { + if(!pszDest) { + if((cchDest!=0) || (cbDest!=0)) hr = STRSAFE_E_INVALID_PARAMETER; + } + if(!pszSrc) pszSrc = ""; + } + if(SUCCEEDED(hr)) { + if(cchDest==0) { + pszDestEnd = pszDest; + cchRemaining = 0; + if((cchToCopy!=0) && (*pszSrc!='\0')) { + if(!pszDest) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + } else { + pszDestEnd = pszDest; + cchRemaining = cchDest; + while(cchRemaining && cchToCopy && (*pszSrc!='\0')) { + *pszDestEnd++ = *pszSrc++; + cchRemaining--; + cchToCopy--; + } + if(cchRemaining > 0) { + if(dwFlags & STRSAFE_FILL_BEHIND_NULL) { + memset(pszDestEnd + 1,STRSAFE_GET_FILL_PATTERN(dwFlags),((cchRemaining - 1)*sizeof(char)) + (cbDest % sizeof(char))); + } + } else { + pszDestEnd--; + cchRemaining++; + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + *pszDestEnd = '\0'; + } + } + } + if(FAILED(hr)) { + if(pszDest) { + if(dwFlags & STRSAFE_FILL_ON_FAILURE) { + memset(pszDest,STRSAFE_GET_FILL_PATTERN(dwFlags),cbDest); + if(STRSAFE_GET_FILL_PATTERN(dwFlags)==0) { + pszDestEnd = pszDest; + cchRemaining = cchDest; + } else if(cchDest > 0) { + pszDestEnd = pszDest + cchDest - 1; + cchRemaining = 1; + *pszDestEnd = '\0'; + } + } + if(dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) { + if(cchDest > 0) { + pszDestEnd = pszDest; + cchRemaining = cchDest; + *pszDestEnd = '\0'; + } + } + } + } + if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER)) { + if(ppszDestEnd) *ppszDestEnd = pszDestEnd; + if(pcchRemaining) *pcchRemaining = cchRemaining; + } + return hr; +} + +STRSAFEAPI StringCopyNExWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,size_t cchToCopy,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags) { + HRESULT hr = S_OK; + STRSAFE_LPWSTR pszDestEnd = pszDest; + size_t cchRemaining = 0; + if(dwFlags & (~STRSAFE_VALID_FLAGS)) hr = STRSAFE_E_INVALID_PARAMETER; + else if(cchToCopy > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else { + if(dwFlags & STRSAFE_IGNORE_NULLS) { + if(!pszDest) { + if((cchDest!=0) || (cbDest!=0)) hr = STRSAFE_E_INVALID_PARAMETER; + } + if(!pszSrc) pszSrc = L""; + } + if(SUCCEEDED(hr)) { + if(cchDest==0) { + pszDestEnd = pszDest; + cchRemaining = 0; + if((cchToCopy!=0) && (*pszSrc!=L'\0')) { + if(!pszDest) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + } else { + pszDestEnd = pszDest; + cchRemaining = cchDest; + while(cchRemaining && cchToCopy && (*pszSrc!=L'\0')) { + *pszDestEnd++ = *pszSrc++; + cchRemaining--; + cchToCopy--; + } + if(cchRemaining > 0) { + if(dwFlags & STRSAFE_FILL_BEHIND_NULL) { + memset(pszDestEnd + 1,STRSAFE_GET_FILL_PATTERN(dwFlags),((cchRemaining - 1)*sizeof(wchar_t)) + (cbDest % sizeof(wchar_t))); + } + } else { + pszDestEnd--; + cchRemaining++; + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + *pszDestEnd = L'\0'; + } + } + } + if(FAILED(hr)) { + if(pszDest) { + if(dwFlags & STRSAFE_FILL_ON_FAILURE) { + memset(pszDest,STRSAFE_GET_FILL_PATTERN(dwFlags),cbDest); + if(STRSAFE_GET_FILL_PATTERN(dwFlags)==0) { + pszDestEnd = pszDest; + cchRemaining = cchDest; + } else if(cchDest > 0) { + pszDestEnd = pszDest + cchDest - 1; + cchRemaining = 1; + *pszDestEnd = L'\0'; + } + } + if(dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) { + if(cchDest > 0) { + pszDestEnd = pszDest; + cchRemaining = cchDest; + *pszDestEnd = L'\0'; + } + } + } + } + if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER)) { + if(ppszDestEnd) *ppszDestEnd = pszDestEnd; + if(pcchRemaining) *pcchRemaining = cchRemaining; + } + return hr; +} + +STRSAFEAPI StringCatWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc) { + HRESULT hr; + size_t cchDestLength; + hr = StringLengthWorkerA(pszDest,cchDest,&cchDestLength); + if(SUCCEEDED(hr)) hr = StringCopyWorkerA(pszDest + cchDestLength,cchDest - cchDestLength,pszSrc); + return hr; +} + +STRSAFEAPI StringCatWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc) { + HRESULT hr; + size_t cchDestLength; + hr = StringLengthWorkerW(pszDest,cchDest,&cchDestLength); + if(SUCCEEDED(hr)) hr = StringCopyWorkerW(pszDest + cchDestLength,cchDest - cchDestLength,pszSrc); + return hr; +} + +STRSAFEAPI StringCatExWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags) { + HRESULT hr = S_OK; + STRSAFE_LPSTR pszDestEnd = pszDest; + size_t cchRemaining = 0; + if(dwFlags & (~STRSAFE_VALID_FLAGS)) hr = STRSAFE_E_INVALID_PARAMETER; + else { + size_t cchDestLength; + if(dwFlags & STRSAFE_IGNORE_NULLS) { + if(!pszDest) { + if((cchDest==0) && (cbDest==0)) cchDestLength = 0; + else hr = STRSAFE_E_INVALID_PARAMETER; + } else { + hr = StringLengthWorkerA(pszDest,cchDest,&cchDestLength); + if(SUCCEEDED(hr)) { + pszDestEnd = pszDest + cchDestLength; + cchRemaining = cchDest - cchDestLength; + } + } + if(!pszSrc) pszSrc = ""; + } else { + hr = StringLengthWorkerA(pszDest,cchDest,&cchDestLength); + if(SUCCEEDED(hr)) { + pszDestEnd = pszDest + cchDestLength; + cchRemaining = cchDest - cchDestLength; + } + } + if(SUCCEEDED(hr)) { + if(cchDest==0) { + if(*pszSrc!='\0') { + if(!pszDest) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + } else hr = StringCopyExWorkerA(pszDestEnd,cchRemaining,(cchRemaining*sizeof(char)) + (cbDest % sizeof(char)),pszSrc,&pszDestEnd,&cchRemaining,dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE))); + } + } + if(FAILED(hr)) { + if(pszDest) { + if(dwFlags & STRSAFE_FILL_ON_FAILURE) { + memset(pszDest,STRSAFE_GET_FILL_PATTERN(dwFlags),cbDest); + if(STRSAFE_GET_FILL_PATTERN(dwFlags)==0) { + pszDestEnd = pszDest; + cchRemaining = cchDest; + } else if(cchDest > 0) { + pszDestEnd = pszDest + cchDest - 1; + cchRemaining = 1; + *pszDestEnd = '\0'; + } + } + if(dwFlags & STRSAFE_NULL_ON_FAILURE) { + if(cchDest > 0) { + pszDestEnd = pszDest; + cchRemaining = cchDest; + *pszDestEnd = '\0'; + } + } + } + } + if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER)) { + if(ppszDestEnd) *ppszDestEnd = pszDestEnd; + if(pcchRemaining) *pcchRemaining = cchRemaining; + } + return hr; +} + +STRSAFEAPI StringCatExWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags) { + HRESULT hr = S_OK; + STRSAFE_LPWSTR pszDestEnd = pszDest; + size_t cchRemaining = 0; + if(dwFlags & (~STRSAFE_VALID_FLAGS)) hr = STRSAFE_E_INVALID_PARAMETER; + else { + size_t cchDestLength; + if(dwFlags & STRSAFE_IGNORE_NULLS) { + if(!pszDest) { + if((cchDest==0) && (cbDest==0)) cchDestLength = 0; + else hr = STRSAFE_E_INVALID_PARAMETER; + } else { + hr = StringLengthWorkerW(pszDest,cchDest,&cchDestLength); + if(SUCCEEDED(hr)) { + pszDestEnd = pszDest + cchDestLength; + cchRemaining = cchDest - cchDestLength; + } + } + if(!pszSrc) pszSrc = L""; + } else { + hr = StringLengthWorkerW(pszDest,cchDest,&cchDestLength); + if(SUCCEEDED(hr)) { + pszDestEnd = pszDest + cchDestLength; + cchRemaining = cchDest - cchDestLength; + } + } + if(SUCCEEDED(hr)) { + if(cchDest==0) { + if(*pszSrc!=L'\0') { + if(!pszDest) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + } else hr = StringCopyExWorkerW(pszDestEnd,cchRemaining,(cchRemaining*sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)),pszSrc,&pszDestEnd,&cchRemaining,dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE))); + } + } + if(FAILED(hr)) { + if(pszDest) { + if(dwFlags & STRSAFE_FILL_ON_FAILURE) { + memset(pszDest,STRSAFE_GET_FILL_PATTERN(dwFlags),cbDest); + if(STRSAFE_GET_FILL_PATTERN(dwFlags)==0) { + pszDestEnd = pszDest; + cchRemaining = cchDest; + } else if(cchDest > 0) { + pszDestEnd = pszDest + cchDest - 1; + cchRemaining = 1; + *pszDestEnd = L'\0'; + } + } + if(dwFlags & STRSAFE_NULL_ON_FAILURE) { + if(cchDest > 0) { + pszDestEnd = pszDest; + cchRemaining = cchDest; + *pszDestEnd = L'\0'; + } + } + } + } + if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER)) { + if(ppszDestEnd) *ppszDestEnd = pszDestEnd; + if(pcchRemaining) *pcchRemaining = cchRemaining; + } + return hr; +} + +STRSAFEAPI StringCatNWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,size_t cchToAppend) { + HRESULT hr; + size_t cchDestLength; + hr = StringLengthWorkerA(pszDest,cchDest,&cchDestLength); + if(SUCCEEDED(hr)) hr = StringCopyNWorkerA(pszDest + cchDestLength,cchDest - cchDestLength,pszSrc,cchToAppend); + return hr; +} + +STRSAFEAPI StringCatNWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,size_t cchToAppend) { + HRESULT hr; + size_t cchDestLength; + hr = StringLengthWorkerW(pszDest,cchDest,&cchDestLength); + if(SUCCEEDED(hr)) hr = StringCopyNWorkerW(pszDest + cchDestLength,cchDest - cchDestLength,pszSrc,cchToAppend); + return hr; +} + +STRSAFEAPI StringCatNExWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,size_t cchToAppend,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags) { + HRESULT hr = S_OK; + STRSAFE_LPSTR pszDestEnd = pszDest; + size_t cchRemaining = 0; + size_t cchDestLength = 0; + if(dwFlags & (~STRSAFE_VALID_FLAGS)) hr = STRSAFE_E_INVALID_PARAMETER; + else if(cchToAppend > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else { + if(dwFlags & STRSAFE_IGNORE_NULLS) { + if(!pszDest) { + if((cchDest==0) && (cbDest==0)) cchDestLength = 0; + else hr = STRSAFE_E_INVALID_PARAMETER; + } else { + hr = StringLengthWorkerA(pszDest,cchDest,&cchDestLength); + if(SUCCEEDED(hr)) { + pszDestEnd = pszDest + cchDestLength; + cchRemaining = cchDest - cchDestLength; + } + } + if(!pszSrc) pszSrc = ""; + } else { + hr = StringLengthWorkerA(pszDest,cchDest,&cchDestLength); + if(SUCCEEDED(hr)) { + pszDestEnd = pszDest + cchDestLength; + cchRemaining = cchDest - cchDestLength; + } + } + if(SUCCEEDED(hr)) { + if(cchDest==0) { + if((cchToAppend!=0) && (*pszSrc!='\0')) { + if(!pszDest) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + } else hr = StringCopyNExWorkerA(pszDestEnd,cchRemaining,(cchRemaining*sizeof(char)) + (cbDest % sizeof(char)),pszSrc,cchToAppend,&pszDestEnd,&cchRemaining,dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE))); + } + } + if(FAILED(hr)) { + if(pszDest) { + if(dwFlags & STRSAFE_FILL_ON_FAILURE) { + memset(pszDest,STRSAFE_GET_FILL_PATTERN(dwFlags),cbDest); + if(STRSAFE_GET_FILL_PATTERN(dwFlags)==0) { + pszDestEnd = pszDest; + cchRemaining = cchDest; + } else if(cchDest > 0) { + pszDestEnd = pszDest + cchDest - 1; + cchRemaining = 1; + *pszDestEnd = '\0'; + } + } + if(dwFlags & (STRSAFE_NULL_ON_FAILURE)) { + if(cchDest > 0) { + pszDestEnd = pszDest; + cchRemaining = cchDest; + *pszDestEnd = '\0'; + } + } + } + } + if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER)) { + if(ppszDestEnd) *ppszDestEnd = pszDestEnd; + if(pcchRemaining) *pcchRemaining = cchRemaining; + } + return hr; +} + +STRSAFEAPI StringCatNExWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,size_t cchToAppend,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags) { + HRESULT hr = S_OK; + STRSAFE_LPWSTR pszDestEnd = pszDest; + size_t cchRemaining = 0; + size_t cchDestLength = 0; + if(dwFlags & (~STRSAFE_VALID_FLAGS)) hr = STRSAFE_E_INVALID_PARAMETER; + else if(cchToAppend > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER; + else { + if(dwFlags & STRSAFE_IGNORE_NULLS) { + if(!pszDest) { + if((cchDest==0) && (cbDest==0)) cchDestLength = 0; + else hr = STRSAFE_E_INVALID_PARAMETER; + } else { + hr = StringLengthWorkerW(pszDest,cchDest,&cchDestLength); + if(SUCCEEDED(hr)) { + pszDestEnd = pszDest + cchDestLength; + cchRemaining = cchDest - cchDestLength; + } + } + if(!pszSrc) pszSrc = L""; + } else { + hr = StringLengthWorkerW(pszDest,cchDest,&cchDestLength); + if(SUCCEEDED(hr)) { + pszDestEnd = pszDest + cchDestLength; + cchRemaining = cchDest - cchDestLength; + } + } + if(SUCCEEDED(hr)) { + if(cchDest==0) { + if((cchToAppend!=0) && (*pszSrc!=L'\0')) { + if(!pszDest) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + } else hr = StringCopyNExWorkerW(pszDestEnd,cchRemaining,(cchRemaining*sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)),pszSrc,cchToAppend,&pszDestEnd,&cchRemaining,dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE))); + } + } + if(FAILED(hr)) { + if(pszDest) { + if(dwFlags & STRSAFE_FILL_ON_FAILURE) { + memset(pszDest,STRSAFE_GET_FILL_PATTERN(dwFlags),cbDest); + if(STRSAFE_GET_FILL_PATTERN(dwFlags)==0) { + pszDestEnd = pszDest; + cchRemaining = cchDest; + } else if(cchDest > 0) { + pszDestEnd = pszDest + cchDest - 1; + cchRemaining = 1; + *pszDestEnd = L'\0'; + } + } + if(dwFlags & (STRSAFE_NULL_ON_FAILURE)) { + if(cchDest > 0) { + pszDestEnd = pszDest; + cchRemaining = cchDest; + *pszDestEnd = L'\0'; + } + } + } + } + if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER)) { + if(ppszDestEnd) *ppszDestEnd = pszDestEnd; + if(pcchRemaining) *pcchRemaining = cchRemaining; + } + return hr; +} + +STRSAFEAPI StringVPrintfWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszFormat,va_list argList) { + HRESULT hr = S_OK; + if(cchDest==0) hr = STRSAFE_E_INVALID_PARAMETER; + else { + int iRet; + size_t cchMax; + cchMax = cchDest - 1; + iRet = _vsnprintf(pszDest,cchMax,pszFormat,argList); + if((iRet < 0) || (((size_t)iRet) > cchMax)) { + pszDest += cchMax; + *pszDest = '\0'; + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } else if(((size_t)iRet)==cchMax) { + pszDest += cchMax; + *pszDest = '\0'; + } + } + return hr; +} + +STRSAFEAPI StringVPrintfWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszFormat,va_list argList) { + HRESULT hr = S_OK; + if(cchDest==0) hr = STRSAFE_E_INVALID_PARAMETER; + else { + int iRet; + size_t cchMax; + cchMax = cchDest - 1; + iRet = _vsnwprintf(pszDest,cchMax,pszFormat,argList); + if((iRet < 0) || (((size_t)iRet) > cchMax)) { + pszDest += cchMax; + *pszDest = L'\0'; + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } else if(((size_t)iRet)==cchMax) { + pszDest += cchMax; + *pszDest = L'\0'; + } + } + return hr; +} + +STRSAFEAPI StringVPrintfExWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags,STRSAFE_LPCSTR pszFormat,va_list argList) { + HRESULT hr = S_OK; + STRSAFE_LPSTR pszDestEnd = pszDest; + size_t cchRemaining = 0; + if(dwFlags & (~STRSAFE_VALID_FLAGS)) hr = STRSAFE_E_INVALID_PARAMETER; + else { + if(dwFlags & STRSAFE_IGNORE_NULLS) { + if(!pszDest) { + if((cchDest!=0) || (cbDest!=0)) hr = STRSAFE_E_INVALID_PARAMETER; + } + if(!pszFormat) pszFormat = ""; + } + if(SUCCEEDED(hr)) { + if(cchDest==0) { + pszDestEnd = pszDest; + cchRemaining = 0; + if(*pszFormat!='\0') { + if(!pszDest) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + } else { + int iRet; + size_t cchMax; + cchMax = cchDest - 1; + iRet = _vsnprintf(pszDest,cchMax,pszFormat,argList); + if((iRet < 0) || (((size_t)iRet) > cchMax)) { + pszDestEnd = pszDest + cchMax; + cchRemaining = 1; + *pszDestEnd = '\0'; + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } else if(((size_t)iRet)==cchMax) { + pszDestEnd = pszDest + cchMax; + cchRemaining = 1; + *pszDestEnd = '\0'; + } else if(((size_t)iRet) < cchMax) { + pszDestEnd = pszDest + iRet; + cchRemaining = cchDest - iRet; + if(dwFlags & STRSAFE_FILL_BEHIND_NULL) { + memset(pszDestEnd + 1,STRSAFE_GET_FILL_PATTERN(dwFlags),((cchRemaining - 1)*sizeof(char)) + (cbDest % sizeof(char))); + } + } + } + } + } + if(FAILED(hr)) { + if(pszDest) { + if(dwFlags & STRSAFE_FILL_ON_FAILURE) { + memset(pszDest,STRSAFE_GET_FILL_PATTERN(dwFlags),cbDest); + if(STRSAFE_GET_FILL_PATTERN(dwFlags)==0) { + pszDestEnd = pszDest; + cchRemaining = cchDest; + } else if(cchDest > 0) { + pszDestEnd = pszDest + cchDest - 1; + cchRemaining = 1; + *pszDestEnd = '\0'; + } + } + if(dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) { + if(cchDest > 0) { + pszDestEnd = pszDest; + cchRemaining = cchDest; + *pszDestEnd = '\0'; + } + } + } + } + if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER)) { + if(ppszDestEnd) *ppszDestEnd = pszDestEnd; + if(pcchRemaining) *pcchRemaining = cchRemaining; + } + return hr; +} + +STRSAFEAPI StringVPrintfExWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags,STRSAFE_LPCWSTR pszFormat,va_list argList) { + HRESULT hr = S_OK; + STRSAFE_LPWSTR pszDestEnd = pszDest; + size_t cchRemaining = 0; + if(dwFlags & (~STRSAFE_VALID_FLAGS)) hr = STRSAFE_E_INVALID_PARAMETER; + else { + if(dwFlags & STRSAFE_IGNORE_NULLS) { + if(!pszDest) { + if((cchDest!=0) || (cbDest!=0)) hr = STRSAFE_E_INVALID_PARAMETER; + } + if(!pszFormat) pszFormat = L""; + } + if(SUCCEEDED(hr)) { + if(cchDest==0) { + pszDestEnd = pszDest; + cchRemaining = 0; + if(*pszFormat!=L'\0') { + if(!pszDest) hr = STRSAFE_E_INVALID_PARAMETER; + else hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + } else { + int iRet; + size_t cchMax; + cchMax = cchDest - 1; + iRet = _vsnwprintf(pszDest,cchMax,pszFormat,argList); + if((iRet < 0) || (((size_t)iRet) > cchMax)) { + pszDestEnd = pszDest + cchMax; + cchRemaining = 1; + *pszDestEnd = L'\0'; + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } else if(((size_t)iRet)==cchMax) { + pszDestEnd = pszDest + cchMax; + cchRemaining = 1; + *pszDestEnd = L'\0'; + } else if(((size_t)iRet) < cchMax) { + pszDestEnd = pszDest + iRet; + cchRemaining = cchDest - iRet; + if(dwFlags & STRSAFE_FILL_BEHIND_NULL) { + memset(pszDestEnd + 1,STRSAFE_GET_FILL_PATTERN(dwFlags),((cchRemaining - 1)*sizeof(wchar_t)) + (cbDest % sizeof(wchar_t))); + } + } + } + } + } + if(FAILED(hr)) { + if(pszDest) { + if(dwFlags & STRSAFE_FILL_ON_FAILURE) { + memset(pszDest,STRSAFE_GET_FILL_PATTERN(dwFlags),cbDest); + if(STRSAFE_GET_FILL_PATTERN(dwFlags)==0) { + pszDestEnd = pszDest; + cchRemaining = cchDest; + } else if(cchDest > 0) { + pszDestEnd = pszDest + cchDest - 1; + cchRemaining = 1; + *pszDestEnd = L'\0'; + } + } + if(dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) { + if(cchDest > 0) { + pszDestEnd = pszDest; + cchRemaining = cchDest; + *pszDestEnd = L'\0'; + } + } + } + } + if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER)) { + if(ppszDestEnd) *ppszDestEnd = pszDestEnd; + if(pcchRemaining) *pcchRemaining = cchRemaining; + } + return hr; +} + +STRSAFEAPI StringLengthWorkerA(STRSAFE_LPCSTR psz,size_t cchMax,size_t *pcchLength) { + HRESULT hr = S_OK; + size_t cchMaxPrev = cchMax; + while(cchMax && (*psz!='\0')) { + psz++; + cchMax--; + } + if(cchMax==0) hr = STRSAFE_E_INVALID_PARAMETER; + if(pcchLength) { + if(SUCCEEDED(hr)) *pcchLength = cchMaxPrev - cchMax; + else *pcchLength = 0; + } + return hr; +} + +STRSAFEAPI StringLengthWorkerW(STRSAFE_LPCWSTR psz,size_t cchMax,size_t *pcchLength) { + HRESULT hr = S_OK; + size_t cchMaxPrev = cchMax; + while(cchMax && (*psz!=L'\0')) { + psz++; + cchMax--; + } + if(cchMax==0) hr = STRSAFE_E_INVALID_PARAMETER; + if(pcchLength) { + if(SUCCEEDED(hr)) *pcchLength = cchMaxPrev - cchMax; + else *pcchLength = 0; + } + return hr; +} + +STRSAFE_INLINE_API StringGetsExWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags) { + HRESULT hr = S_OK; + STRSAFE_LPSTR pszDestEnd = pszDest; + size_t cchRemaining = 0; + + if(dwFlags & (~STRSAFE_VALID_FLAGS)) hr = STRSAFE_E_INVALID_PARAMETER; + else { + if(dwFlags & STRSAFE_IGNORE_NULLS) { + if(!pszDest) { + if((cchDest!=0) || (cbDest!=0)) hr = STRSAFE_E_INVALID_PARAMETER; + } + } + if(SUCCEEDED(hr)) { + if(cchDest <= 1) { + pszDestEnd = pszDest; + cchRemaining = cchDest; + if(cchDest==1) *pszDestEnd = '\0'; + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } else { + pszDestEnd = pszDest; + cchRemaining = cchDest; + while(cchRemaining > 1) { + char ch; + int i = getc(stdin); + if(i==EOF) { + if(pszDestEnd==pszDest) hr = STRSAFE_E_END_OF_FILE; + break; + } + ch = (char)i; + if(ch=='\n') break; + *pszDestEnd = ch; + pszDestEnd++; + cchRemaining--; + } + if(cchRemaining > 0) { + if(dwFlags & STRSAFE_FILL_BEHIND_NULL) { + memset(pszDestEnd + 1,STRSAFE_GET_FILL_PATTERN(dwFlags),((cchRemaining - 1)*sizeof(char)) + (cbDest % sizeof(char))); + } + } + *pszDestEnd = '\0'; + } + } + } + if(FAILED(hr)) { + if(pszDest) { + if(dwFlags & STRSAFE_FILL_ON_FAILURE) { + memset(pszDest,STRSAFE_GET_FILL_PATTERN(dwFlags),cbDest); + if(STRSAFE_GET_FILL_PATTERN(dwFlags)==0) { + pszDestEnd = pszDest; + cchRemaining = cchDest; + } else if(cchDest > 0) { + pszDestEnd = pszDest + cchDest - 1; + cchRemaining = 1; + *pszDestEnd = '\0'; + } + } + if(dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) { + if(cchDest > 0) { + pszDestEnd = pszDest; + cchRemaining = cchDest; + *pszDestEnd = '\0'; + } + } + } + } + if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER) || (hr==STRSAFE_E_END_OF_FILE)) { + if(ppszDestEnd) *ppszDestEnd = pszDestEnd; + if(pcchRemaining) *pcchRemaining = cchRemaining; + } + return hr; +} + +STRSAFE_INLINE_API StringGetsExWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,unsigned long dwFlags) { + HRESULT hr = S_OK; + STRSAFE_LPWSTR pszDestEnd = pszDest; + size_t cchRemaining = 0; + if(dwFlags & (~STRSAFE_VALID_FLAGS)) { + hr = STRSAFE_E_INVALID_PARAMETER; + } else { + if(dwFlags & STRSAFE_IGNORE_NULLS) { + if(!pszDest) { + if((cchDest!=0) || (cbDest!=0)) hr = STRSAFE_E_INVALID_PARAMETER; + } + } + if(SUCCEEDED(hr)) { + if(cchDest <= 1) { + pszDestEnd = pszDest; + cchRemaining = cchDest; + if(cchDest==1) *pszDestEnd = L'\0'; + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } else { + pszDestEnd = pszDest; + cchRemaining = cchDest; + while(cchRemaining > 1) { + wchar_t ch = getwc(stdin); + if(ch==WEOF) { + if(pszDestEnd==pszDest) hr = STRSAFE_E_END_OF_FILE; + break; + } + if(ch==L'\n') break; + *pszDestEnd = ch; + pszDestEnd++; + cchRemaining--; + } + if(cchRemaining > 0) { + if(dwFlags & STRSAFE_FILL_BEHIND_NULL) { + memset(pszDestEnd + 1,STRSAFE_GET_FILL_PATTERN(dwFlags),((cchRemaining - 1)*sizeof(wchar_t)) + (cbDest % sizeof(wchar_t))); + } + } + *pszDestEnd = L'\0'; + } + } + } + if(FAILED(hr)) { + if(pszDest) { + if(dwFlags & STRSAFE_FILL_ON_FAILURE) { + memset(pszDest,STRSAFE_GET_FILL_PATTERN(dwFlags),cbDest); + if(STRSAFE_GET_FILL_PATTERN(dwFlags)==0) { + pszDestEnd = pszDest; + cchRemaining = cchDest; + } else if(cchDest > 0) { + pszDestEnd = pszDest + cchDest - 1; + cchRemaining = 1; + *pszDestEnd = L'\0'; + } + } + if(dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) { + if(cchDest > 0) { + pszDestEnd = pszDest; + cchRemaining = cchDest; + *pszDestEnd = L'\0'; + } + } + } + } + if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER) || (hr==STRSAFE_E_END_OF_FILE)) { + if(ppszDestEnd) *ppszDestEnd = pszDestEnd; + if(pcchRemaining) *pcchRemaining = cchRemaining; + } + return hr; +} +#endif /* !__CRT__NO_INLINE */ + +#define StringCopyWorkerA StringCopyWorkerA_instead_use_StringCchCopyA_or_StringCchCopyExA; +#define StringCopyWorkerW StringCopyWorkerW_instead_use_StringCchCopyW_or_StringCchCopyExW; +#define StringCopyExWorkerA StringCopyExWorkerA_instead_use_StringCchCopyA_or_StringCchCopyExA; +#define StringCopyExWorkerW StringCopyExWorkerW_instead_use_StringCchCopyW_or_StringCchCopyExW; +#define StringCatWorkerA StringCatWorkerA_instead_use_StringCchCatA_or_StringCchCatExA; +#define StringCatWorkerW StringCatWorkerW_instead_use_StringCchCatW_or_StringCchCatExW; +#define StringCatExWorkerA StringCatExWorkerA_instead_use_StringCchCatA_or_StringCchCatExA; +#define StringCatExWorkerW StringCatExWorkerW_instead_use_StringCchCatW_or_StringCchCatExW; +#define StringCatNWorkerA StringCatNWorkerA_instead_use_StringCchCatNA_or_StrincCbCatNA; +#define StringCatNWorkerW StringCatNWorkerW_instead_use_StringCchCatNW_or_StringCbCatNW; +#define StringCatNExWorkerA StringCatNExWorkerA_instead_use_StringCchCatNExA_or_StringCbCatNExA; +#define StringCatNExWorkerW StringCatNExWorkerW_instead_use_StringCchCatNExW_or_StringCbCatNExW; +#define StringVPrintfWorkerA StringVPrintfWorkerA_instead_use_StringCchVPrintfA_or_StringCchVPrintfExA; +#define StringVPrintfWorkerW StringVPrintfWorkerW_instead_use_StringCchVPrintfW_or_StringCchVPrintfExW; +#define StringVPrintfExWorkerA StringVPrintfExWorkerA_instead_use_StringCchVPrintfA_or_StringCchVPrintfExA; +#define StringVPrintfExWorkerW StringVPrintfExWorkerW_instead_use_StringCchVPrintfW_or_StringCchVPrintfExW; +#define StringLengthWorkerA StringLengthWorkerA_instead_use_StringCchLengthA_or_StringCbLengthA; +#define StringLengthWorkerW StringLengthWorkerW_instead_use_StringCchLengthW_or_StringCbLengthW; +#define StringGetsExWorkerA StringGetsExWorkerA_instead_use_StringCchGetsA_or_StringCbGetsA +#define StringGetsExWorkerW StringGetsExWorkerW_instead_use_StringCchGetsW_or_StringCbGetsW + +#ifndef STRSAFE_NO_DEPRECATE + +#undef strcpy +#define strcpy strcpy_instead_use_StringCbCopyA_or_StringCchCopyA; + +#undef wcscpy +#define wcscpy wcscpy_instead_use_StringCbCopyW_or_StringCchCopyW; + +#undef strcat +#define strcat strcat_instead_use_StringCbCatA_or_StringCchCatA; + +#undef wcscat +#define wcscat wcscat_instead_use_StringCbCatW_or_StringCchCatW; + +#undef sprintf +#define sprintf sprintf_instead_use_StringCbPrintfA_or_StringCchPrintfA; + +#undef swprintf +#define swprintf swprintf_instead_use_StringCbPrintfW_or_StringCchPrintfW; + +#undef vsprintf +#define vsprintf vsprintf_instead_use_StringCbVPrintfA_or_StringCchVPrintfA; + +#undef vswprintf +#define vswprintf vswprintf_instead_use_StringCbVPrintfW_or_StringCchVPrintfW; + +#undef _snprintf +#define _snprintf _snprintf_instead_use_StringCbPrintfA_or_StringCchPrintfA; + +#undef _snwprintf +#define _snwprintf _snwprintf_instead_use_StringCbPrintfW_or_StringCchPrintfW; + +#undef _vsnprintf +#define _vsnprintf _vsnprintf_instead_use_StringCbVPrintfA_or_StringCchVPrintfA; + +#undef _vsnwprintf +#define _vsnwprintf _vsnwprintf_instead_use_StringCbVPrintfW_or_StringCchVPrintfW; + +#undef strcpyA +#define strcpyA strcpyA_instead_use_StringCbCopyA_or_StringCchCopyA; + +#undef strcpyW +#define strcpyW strcpyW_instead_use_StringCbCopyW_or_StringCchCopyW; + +#undef lstrcpy +#define lstrcpy lstrcpy_instead_use_StringCbCopy_or_StringCchCopy; + +#undef lstrcpyA +#define lstrcpyA lstrcpyA_instead_use_StringCbCopyA_or_StringCchCopyA; + +#undef lstrcpyW +#define lstrcpyW lstrcpyW_instead_use_StringCbCopyW_or_StringCchCopyW; + +#undef StrCpy +#define StrCpy StrCpy_instead_use_StringCbCopy_or_StringCchCopy; + +#undef StrCpyA +#define StrCpyA StrCpyA_instead_use_StringCbCopyA_or_StringCchCopyA; + +#undef StrCpyW +#define StrCpyW StrCpyW_instead_use_StringCbCopyW_or_StringCchCopyW; + +#undef _tcscpy +#define _tcscpy _tcscpy_instead_use_StringCbCopy_or_StringCchCopy; + +#undef _ftcscpy +#define _ftcscpy _ftcscpy_instead_use_StringCbCopy_or_StringCchCopy; + +#undef lstrcat +#define lstrcat lstrcat_instead_use_StringCbCat_or_StringCchCat; + +#undef lstrcatA +#define lstrcatA lstrcatA_instead_use_StringCbCatA_or_StringCchCatA; + +#undef lstrcatW +#define lstrcatW lstrcatW_instead_use_StringCbCatW_or_StringCchCatW; + +#undef StrCat +#define StrCat StrCat_instead_use_StringCbCat_or_StringCchCat; + +#undef StrCatA +#define StrCatA StrCatA_instead_use_StringCbCatA_or_StringCchCatA; + +#undef StrCatW +#define StrCatW StrCatW_instead_use_StringCbCatW_or_StringCchCatW; + +#undef StrNCat +#define StrNCat StrNCat_instead_use_StringCbCatN_or_StringCchCatN; + +#undef StrNCatA +#define StrNCatA StrNCatA_instead_use_StringCbCatNA_or_StringCchCatNA; + +#undef StrNCatW +#define StrNCatW StrNCatW_instead_use_StringCbCatNW_or_StringCchCatNW; + +#undef StrCatN +#define StrCatN StrCatN_instead_use_StringCbCatN_or_StringCchCatN; + +#undef StrCatNA +#define StrCatNA StrCatNA_instead_use_StringCbCatNA_or_StringCchCatNA; + +#undef StrCatNW +#define StrCatNW StrCatNW_instead_use_StringCbCatNW_or_StringCchCatNW; + +#undef _tcscat +#define _tcscat _tcscat_instead_use_StringCbCat_or_StringCchCat; + +#undef _ftcscat +#define _ftcscat _ftcscat_instead_use_StringCbCat_or_StringCchCat; + +#undef wsprintf +#define wsprintf wsprintf_instead_use_StringCbPrintf_or_StringCchPrintf; + +#undef wsprintfA +#define wsprintfA wsprintfA_instead_use_StringCbPrintfA_or_StringCchPrintfA; + +#undef wsprintfW +#define wsprintfW wsprintfW_instead_use_StringCbPrintfW_or_StringCchPrintfW; + +#undef wvsprintf +#define wvsprintf wvsprintf_instead_use_StringCbVPrintf_or_StringCchVPrintf; + +#undef wvsprintfA +#define wvsprintfA wvsprintfA_instead_use_StringCbVPrintfA_or_StringCchVPrintfA; + +#undef wvsprintfW +#define wvsprintfW wvsprintfW_instead_use_StringCbVPrintfW_or_StringCchVPrintfW; + +#undef _vstprintf +#define _vstprintf _vstprintf_instead_use_StringCbVPrintf_or_StringCchVPrintf; + +#undef _vsntprintf +#define _vsntprintf _vsntprintf_instead_use_StringCbVPrintf_or_StringCchVPrintf; + +#undef _stprintf +#define _stprintf _stprintf_instead_use_StringCbPrintf_or_StringCchPrintf; + +#undef _sntprintf +#define _sntprintf _sntprintf_instead_use_StringCbPrintf_or_StringCchPrintf; + +#undef _getts +#define _getts _getts_instead_use_StringCbGets_or_StringCchGets; + +#undef gets +#define gets _gets_instead_use_StringCbGetsA_or_StringCchGetsA; + +#undef _getws +#define _getws _getws_instead_use_StringCbGetsW_or_StringCchGetsW; +#endif +#endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..5922943 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,16 @@ +include ( ${QT_USE_FILE} ) +include_directories ( + ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} + ${QT_QTCORE_INCLUDE_DIR} ${QT_QTGUI_INCLUDE_DIR} + ${QT_QTNETWORK_INCLUDE_DIR} ${QT_QTDBUS_INCLUDE_DIR} + ) + +add_subdirectory(core) + +add_executable ( SnoreNotify main.cpp ) +target_link_libraries ( SnoreNotify snore) +add_dependencies(SnoreNotify snore) + +add_subdirectory(webinterface) +add_subdirectory(plugins) + diff --git a/src/Gui/SnoreNotifyGui.pro b/src/Gui/SnoreNotifyGui.pro new file mode 100644 index 0000000..3f51be7 --- /dev/null +++ b/src/Gui/SnoreNotifyGui.pro @@ -0,0 +1,17 @@ +# ------------------------------------------------- +# Project created by QtCreator 2009-11-24T23:39:55 +# ------------------------------------------------- +QT += dbus +QT += gui +QT += network +TARGET = SnoreNotifyGui +TEMPLATE = app +INCLUDEPATH += ../. ./ +HEADERS += mainwindow.h \ + ../dbusbinding.h \ + ../application.h +FORMS += mainwindow.ui +SOURCES += ../dbusbinding.cpp \ + ../application.cpp \ + gmain.cpp\ + mainwindow.cpp diff --git a/src/Gui/gmain.cpp b/src/Gui/gmain.cpp new file mode 100644 index 0000000..5c9c636 --- /dev/null +++ b/src/Gui/gmain.cpp @@ -0,0 +1,11 @@ +#include +#include "mainwindow.h" + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + DBusBinding::registerTypes(); + MainWindow w; + w.show(); + return a.exec(); +} diff --git a/src/Gui/mainwindow.cpp b/src/Gui/mainwindow.cpp new file mode 100644 index 0000000..d2ffc97 --- /dev/null +++ b/src/Gui/mainwindow.cpp @@ -0,0 +1,75 @@ +#include "mainwindow.h" +#include "ui_mainwindow.h" + + +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent), ui(new Ui::MainWindow) +{ + ui->setupUi(this); + + itemsList_applications=new QStandardItemModel(this); + itemsList_alerts=new QStandardItemModel(this); + ui->listView_applicationList->setModel(itemsList_applications); + ui->listView_AlertList->setModel(itemsList_alerts); + + QDBusReply reply= DBusBinding::snoreInterface.call("getApplicationList"); + if(reply.isValid()) + applicationListChanged(reply); + else + qDebug()<setHorizontalHeaderItem(0,new QStandardItem("Registred Applications")); + applicationList=apls; + itemsList_applications->clear(); + QStandardItem *item; + foreach(const QString &s,applicationList.keys()){ + item=new QStandardItem(s); + item->setEditable(false); + itemsList_applications->appendRow(item); + } + itemsList_alerts->clear(); + if(!currentSelectedApplication.isEmpty()&&applicationList.contains(currentSelectedApplication)){ + + foreach(QSharedPointer al,applicationList.value(currentSelectedApplication)->alerts.values()){ + item=new QStandardItem(al->name); + item->setEnabled(al->active); + item->setEditable(false); + itemsList_alerts->appendRow(item); + } + } +} + + +void MainWindow::on_listView_applicationList_clicked(QModelIndex index) +{ + currentSelectedApplication=itemsList_applications->item(index.row(),index.column())->text(); + itemsList_alerts->setHorizontalHeaderItem(0,new QStandardItem("Alerts")); + itemsList_alerts->setHorizontalHeaderItem(1,new QStandardItem("Active")); + itemsList_alerts->clear(); + QStandardItem *item; + foreach(QSharedPointer al,applicationList.value(currentSelectedApplication)->alerts.values()){ + item=new QStandardItem(al->name); + item->setEnabled(al->active); + itemsList_alerts->appendRow(item); + } + +} + +void MainWindow::on_listView_AlertList_clicked(QModelIndex index) +{ + qDebug()<item(index.row(),index.column())->text(),!itemsList_alerts->item(index.row(),index.column())->isEnabled()); + + +} diff --git a/src/Gui/mainwindow.h b/src/Gui/mainwindow.h new file mode 100644 index 0000000..d47c817 --- /dev/null +++ b/src/Gui/mainwindow.h @@ -0,0 +1,36 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include "application.h" +#include "dbusbinding.h" +#include + +namespace Ui +{ + class MainWindow; +} + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + MainWindow(QWidget *parent = 0); + ~MainWindow(); + ApplicationsList applicationList; + QStandardItemModel* itemsList_applications; + QStandardItemModel* itemsList_alerts; +public slots: + void applicationListChanged(const ApplicationsList &apls); + +private: + Ui::MainWindow *ui; + QString currentSelectedApplication; + +private slots: + void on_listView_AlertList_clicked(QModelIndex index); + void on_listView_applicationList_clicked(QModelIndex index); +}; + +#endif // MAINWINDOW_H diff --git a/src/Gui/mainwindow.ui b/src/Gui/mainwindow.ui new file mode 100644 index 0000000..6a8a66c --- /dev/null +++ b/src/Gui/mainwindow.ui @@ -0,0 +1,61 @@ + + + MainWindow + + + + 0 + 0 + 600 + 400 + + + + Snore Notify + + + + + + 20 + 60 + 141 + 301 + + + + + + + 160 + 60 + 256 + 301 + + + + + + + + 0 + 0 + 600 + 20 + + + + + + TopToolBarArea + + + false + + + + + + + + diff --git a/src/Gui/ui_mainwindow.h b/src/Gui/ui_mainwindow.h new file mode 100644 index 0000000..1cffc88 --- /dev/null +++ b/src/Gui/ui_mainwindow.h @@ -0,0 +1,80 @@ +/******************************************************************************** +** Form generated from reading UI file 'mainwindow.ui' +** +** Created: Tue 29. Dec 01:35:26 2009 +** by: Qt User Interface Compiler version 4.6.0 +** +** WARNING! All changes made in this file will be lost when recompiling UI file! +********************************************************************************/ + +#ifndef UI_MAINWINDOW_H +#define UI_MAINWINDOW_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Ui_MainWindow +{ +public: + QWidget *centralWidget; + QListView *listView_applicationList; + QListView *listView_AlertList; + QMenuBar *menuBar; + QToolBar *mainToolBar; + QStatusBar *statusBar; + + void setupUi(QMainWindow *MainWindow) + { + if (MainWindow->objectName().isEmpty()) + MainWindow->setObjectName(QString::fromUtf8("MainWindow")); + MainWindow->resize(600, 400); + centralWidget = new QWidget(MainWindow); + centralWidget->setObjectName(QString::fromUtf8("centralWidget")); + listView_applicationList = new QListView(centralWidget); + listView_applicationList->setObjectName(QString::fromUtf8("listView_applicationList")); + listView_applicationList->setGeometry(QRect(20, 60, 141, 301)); + listView_AlertList = new QListView(centralWidget); + listView_AlertList->setObjectName(QString::fromUtf8("listView_AlertList")); + listView_AlertList->setGeometry(QRect(160, 60, 256, 301)); + MainWindow->setCentralWidget(centralWidget); + menuBar = new QMenuBar(MainWindow); + menuBar->setObjectName(QString::fromUtf8("menuBar")); + menuBar->setGeometry(QRect(0, 0, 600, 20)); + MainWindow->setMenuBar(menuBar); + mainToolBar = new QToolBar(MainWindow); + mainToolBar->setObjectName(QString::fromUtf8("mainToolBar")); + MainWindow->addToolBar(Qt::TopToolBarArea, mainToolBar); + statusBar = new QStatusBar(MainWindow); + statusBar->setObjectName(QString::fromUtf8("statusBar")); + MainWindow->setStatusBar(statusBar); + + retranslateUi(MainWindow); + + QMetaObject::connectSlotsByName(MainWindow); + } // setupUi + + void retranslateUi(QMainWindow *MainWindow) + { + MainWindow->setWindowTitle(QApplication::translate("MainWindow", "Snore Notify", 0, QApplication::UnicodeUTF8)); + } // retranslateUi + +}; + +namespace Ui { + class MainWindow: public Ui_MainWindow {}; +} // namespace Ui + +QT_END_NAMESPACE + +#endif // UI_MAINWINDOW_H diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt new file mode 100644 index 0000000..6c76de0 --- /dev/null +++ b/src/core/CMakeLists.txt @@ -0,0 +1,12 @@ +set ( SnoreNotify_SRCS + notification.cpp + snoreserver.cpp + application.cpp + interface.cpp + ) + +automoc4_add_library( snore SHARED ${SnoreNotify_SRCS}) +set_target_properties( snore PROPERTIES COMPILE_FLAGS "-DSNORECORE_DLL" ) +target_link_libraries ( snore ${QT_QTCORE_LIBRARY} ) + + diff --git a/src/core/application.cpp b/src/core/application.cpp new file mode 100644 index 0000000..7d70146 --- /dev/null +++ b/src/core/application.cpp @@ -0,0 +1,19 @@ +#include "application.h" + + +Application::Application(const QString &name):name(name){} + +Application::Application():name("Error: Uninitialized Application"){} + +void Application::addAlert(const QString &alert,const QString &title){ + alerts.insert(alert,QSharedPointer(new Alert(alert,title))); +} + + +Alert::Alert(const QString &name,const QString &title):name(name),title(title),active(true){} +Alert::Alert(const QString &name,const QString &title,bool active):name(name),title(title),active(active){} + +Alert::Alert():active(false){} + + + diff --git a/src/core/application.h b/src/core/application.h new file mode 100644 index 0000000..a0397bd --- /dev/null +++ b/src/core/application.h @@ -0,0 +1,35 @@ +#ifndef APPLICATION_H +#define APPLICATION_H +#include "snore_exports.h" +#include +#include +#include +#include +#include + +typedef QHash > ApplicationsList ; +typedef QHash > AlertList; +class SNORE_EXPORT Application +{ +public: + Application(const QString &name); + Application(); + AlertList alerts; + QString name; + + + void addAlert(const QString &alert,const QString &title); +}; + +class SNORE_EXPORT Alert{ +public: + Alert(const QString &name,const QString &title); + Alert(const QString &name,const QString &title,bool active); + Alert(); + QString name; + QString title; + bool active; +}; + + +#endif // APPLICATION_H diff --git a/src/core/interface.cpp b/src/core/interface.cpp new file mode 100644 index 0000000..8d34f1c --- /dev/null +++ b/src/core/interface.cpp @@ -0,0 +1,14 @@ +#include "interface.h" +#include "snoreserver.h" + + +void SnorePlugin::setSnore(SnoreServer *snore){ + this->snore=snore; +} + +SnoreServer* SnorePlugin::getSnore(){ + return snore.data(); +} + + +#include "interface.moc" diff --git a/src/core/interface.h b/src/core/interface.h new file mode 100644 index 0000000..025eea8 --- /dev/null +++ b/src/core/interface.h @@ -0,0 +1,53 @@ +#ifndef INTERFACE_H +#define INTERFACE_H +#include "snore_exports.h" +#include "notification.h" +#include +#include +#include +#include + +class SNORE_EXPORT SnorePlugin{ +public: + virtual ~SnorePlugin(){}; + virtual void setSnore(class SnoreServer* snore); + virtual class SnoreServer* getSnore(); +private: + QPointer snore; + +}; + +class SNORE_EXPORT Notification_Backend:public QObject,public SnorePlugin +{ + Q_OBJECT +public: + virtual ~Notification_Backend() {} + virtual bool isPrimaryNotificationBackend()=0; + +public slots: + virtual int notify(QSharedPointer notification)=0; + virtual void closeNotification(int id)=0; + + // virtual void update + +}; + + +class SNORE_EXPORT Notification_Frontend:public SnorePlugin{ +public: + virtual ~Notification_Frontend() {} + virtual void actionInvoked(QSharedPointer notification)=0; + virtual void notificationClosed(QSharedPointer notification)=0; +}; + + + +Q_DECLARE_INTERFACE(SnorePlugin, + "org.Snore.SnorePlugin/1.0") +Q_DECLARE_INTERFACE(Notification_Frontend, + "org.Snore.NotificationFrontend/1.0") +Q_DECLARE_INTERFACE(Notification_Backend, + "org.Snore.NotificationBackend/1.0") + + +#endif//INTERFACE_H diff --git a/src/core/libgrowl.h b/src/core/libgrowl.h new file mode 100644 index 0000000..0f08402 --- /dev/null +++ b/src/core/libgrowl.h @@ -0,0 +1,9 @@ +#ifndef LIBGROWL_H +#define LIBGROWL_H + +//registers all alert classes in the aray as default alerts +void reister(string classes[]); +//send a notification and return its registration id +int send(string title,string body,string iconPath,int timeout); + +#endif // LIBGROWL_H diff --git a/src/core/notification.cpp b/src/core/notification.cpp new file mode 100644 index 0000000..736f3a5 --- /dev/null +++ b/src/core/notification.cpp @@ -0,0 +1,38 @@ +#include "notification.h" +#include +#include +#include "snoreserver.h" + + +Notification::Notification():source("none"),timeout(10),notification(true){} +Notification::Notification(QString source,QString title,QString text,QString icon,int timeout):source(source),title(title),text(text),timeout(timeout),icon(icon),notification(true) +{ +} + +QString Notification::getIcon(){ + return icon; +} + +bool Notification::isNotification(){ + return notification; +} + + +QString Notification::toSnalrString()const{ + QString out("type=SNP#?version=1.1"); + if(hints.contains("SNaction")) + out+=QString("#?action="+hints.value("SNaction").value()); + if(!app.isEmpty()) + out+=QString("#?app="+app); + if(!alert.isEmpty()) + out+=QString("#?class="+alert); + out+=QString("#?title="+title+"#?text="+text+"#?timeout="+QString::number(timeout)); + return out; +} + +QDataStream & operator<< ( QDataStream & stream, const Notification & noti){ + stream< +#include +#include +#include +#include +#include "QHash" +#include +#include "application.h" +#include + + + + + +class SNORE_EXPORT Notification:public QObject +{ + Q_OBJECT +public: + Notification(); + Notification(QString source,QString title,QString text,QString icon,int timeout); + bool isNotification(); + QString toSnalrString()const; + + enum actions{ + TIMED_OUT=0, + ACTION_1=1, + ACTION_2=2, + ACTION_3=3, + CLOSED=4 + + }; + + actions actionInvoked; + QString source; + QString app; + QString title; + QString text; + QString alert; + int timeout; + void setIcon(const QString &icon){this->icon=icon; } + QString getIcon(); + + QVariantHash hints; + + int id; + + + + + + +private: + QString icon; + bool notification; + + + +}; + +QDataStream & operator<< ( QDataStream & stream, const Notification & noti); + +#endif // NOTIFICATION_H diff --git a/src/core/snore_exports.h b/src/core/snore_exports.h new file mode 100644 index 0000000..a2c062a --- /dev/null +++ b/src/core/snore_exports.h @@ -0,0 +1,12 @@ +#ifndef SNORE_EXPORT_H +#define SNORE_EXPORT_H + + +#ifdef SNORECORE_DLL +# define SNORE_EXPORT Q_DECL_EXPORT +#else +# define SNORE_EXPORT Q_DECL_IMPORT +#endif + + +#endif//SNORE_EXPORT_H diff --git a/src/core/snoreserver.cpp b/src/core/snoreserver.cpp new file mode 100644 index 0000000..b2b7824 --- /dev/null +++ b/src/core/snoreserver.cpp @@ -0,0 +1,101 @@ +#include "snoreserver.h" +#include +#include "notification.h" +#include + + +QString const SnoreServer::snoreTMP=QDir::temp().path()+"/SnoreNotify"; + +SnoreServer::SnoreServer():primaryNotificationBackend(0) +{ qDebug()<<"Inititalized"; + QDir home(snoreTMP); + if(home.exists()){ + QStringList filetypes; + filetypes<<"*.png"<<"*.jpg"; + QStringList toDell; + toDell=home.entryList(filetypes); + foreach(QString s,toDell){ + home.remove(s); + } + + }else + QDir::temp().mkpath("SnoreNotify"); +} + +void SnoreServer::publicatePlugin(QObject *plugin){ + qDebug()<<"Loading plugin: "<property("name").value(); + + + SnorePlugin *sp=qobject_cast(plugin); + if(sp){ + plugins.insert(plugin->property("name").value(),plugin); + qDebug()<property("name").value()<<"is a SnorePlugin"; + sp->setSnore(this); + } + Notification_Frontend *nf=qobject_cast(plugin); + if(nf){ + qDebug()<property("name").value()<<"is a Notification_Frontend"; + nf->setSnore(this); + + } + + Notification_Backend * nb=qobject_cast(plugin); + if(nb){ + qDebug()<property("name").value()<<"is a Notification_Backend"; + if(nb->isPrimaryNotificationBackend()) + primaryNotificationBackend=nb; + else{ + notyfier.append(nb); + connect(this,SIGNAL(notify(QSharedPointer)),nb,SLOT(notify(QSharedPointer))); + } + connect(this,SIGNAL(closeNotify(int)),nb,SLOT(closeNotification(int))); + nb->setSnore(this); + } +} + +int SnoreServer::broadcastNotification(QSharedPointer notification){ + emit notify(notification); + qDebug()<<"Broadcasting notification:"<toSnalrString(); + if(primaryNotificationBackend!=NULL){ + return primaryNotificationBackend->notify(notification); + } + return -1; +} + +void SnoreServer::closeNotification(QSharedPointer notification){ + emit closeNotify(notification->id); + Notification_Frontend *nf= qobject_cast(plugins.value(notification->source)); + if(nf!=0){ + nf->notificationClosed(notification); + } +} + +void SnoreServer::notificationActionInvoked(QSharedPointer notification){ + Notification_Frontend *nf= qobject_cast(plugins.value(notification->source)); + if(nf!=0){ + nf->actionInvoked(notification); + } +} + +void SnoreServer::addApplication(QSharedPointer application){ + applications.insert(application->name,application); + emit applicationListChanged(); +} + + +bool SnoreServer::applicationListConontainsAlert(const QString &applicationName,const QString &alertName){ + return applications.contains(applicationName)&&applications.value(applicationName)->alerts.contains(alertName) + &&!applications.value(applicationName)->alerts.value(alertName)->active; +} + +void SnoreServer::addAlert(const QString &appName,const QString &alertName, const QString &alertTitle){ + applications.value(appName)->addAlert(alertName,alertTitle); + emit applicationListChanged(); +} + +void SnoreServer::removeApplication(const QString& appName){ + applications.take(appName).clear(); + emit applicationListChanged(); +} + +#include "snoreserver.moc" diff --git a/src/core/snoreserver.h b/src/core/snoreserver.h new file mode 100644 index 0000000..17ae383 --- /dev/null +++ b/src/core/snoreserver.h @@ -0,0 +1,60 @@ +#ifndef SNORESERVER_H +#define SNORESERVER_H +#include "snore_exports.h" +#include +#include +#include +#include +#include +#include +#include +#include "application.h" +#include +#include "interface.h" +#include + + +class SNORE_EXPORT SnoreServer:public QObject +{ + Q_OBJECT +public: + static const QString snoreTMP; + + +public: + SnoreServer(); + void publicatePlugin(QObject* plugin); + + + int broadcastNotification(QSharedPointer notification); + void closeNotification(QSharedPointer notification); + void notificationActionInvoked(QSharedPointer notification); + + void addApplication(QSharedPointer application); + bool applicationListConontainsAlert(const QString &applicationName,const QString &alertName); + void addAlert(const QString &appName,const QString &alertName, const QString &alertTitle); + void removeApplication(const QString& appName); + + ApplicationsList* getAplicationList(){ + return &applications; + } + + QHash plugins; + +private: + ApplicationsList applications; + + + QList notyfier; + Notification_Backend * primaryNotificationBackend; + + +signals: + void applicationListChanged(); + void notify(QSharedPointer noti); + void closeNotify(int id); + +}; + + +#endif // SNORESERVER_H diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..5fbff42 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,28 @@ +#include +#include "core/snoreserver.h" +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) +{ + QCoreApplication a(argc, argv); + SnoreServer s; + + QDir pluginsDir(a.applicationDirPath()+"/plugins"); + foreach (QString fileName, pluginsDir.entryList(QDir::Files)) { + QPluginLoader loader(pluginsDir.absoluteFilePath(fileName)); + QObject *plugin = loader.instance(); + if (plugin) { + s.publicatePlugin(plugin); + }else + qDebug()<<"Failed loading plugin: "< + +Q_EXPORT_PLUGIN2(dbusbinding,DBusPlugin) + +void DBusPlugin::setSnore(SnoreServer *snore){ + new DBusBinding(this,snore); +} + +DBusBinding::DBusBinding(DBusPlugin* parent,SnoreServer* snore):QDBusAbstractAdaptor(parent),snore(snore){ + registerTypes(); + QDBusConnection dbus = QDBusConnection::sessionBus(); + dbus.registerService( "org.SnoreNotify" ); + dbus.registerObject( "/SnoreNotify", this ); + connect(snore,SIGNAL(applicationListChanged()),this,SLOT(applicationListChangedSlot())); +} +DBusBinding::~DBusBinding(){ + QDBusConnection dbus = QDBusConnection::sessionBus(); + dbus.unregisterService( "/SnoreNotify" ); +} + + +void DBusBinding::registerTypes(){ + qDBusRegisterMetaType(); + qDBusRegisterMetaType(); + qDBusRegisterMetaType(); + qDBusRegisterMetaType(); +} + + +ApplicationsList DBusBinding::getApplicationList(){ + //workaround for the "" application bug + if(snore->getAplicationList()->contains("")){ + snore->getAplicationList()->take("").clear(); + qDebug()<<"Removed wrong entry ("") in application list"; + } + + return *snore->getAplicationList(); +} + +void DBusBinding::setAlertActive(const QString &application,const QString &name,const bool active){ + QSharedPointer ap(snore->getAplicationList()->value(application)); + ap->alerts.value(name)->active=active; + emit applicationListChanged(*snore->getAplicationList()); +} + + +void DBusBinding::applicationListChangedSlot(){ + emit applicationListChanged(*snore->getAplicationList()); +} + + +QDBusArgument &operator<<(QDBusArgument &a, const ApplicationsList &ap) { + a.beginArray(qMetaTypeId()); + qDebug()<<"ApplicationList:"< appl,ap.values()){ + a<<*appl.data(); + } + a.endArray(); + return a; +} + +const QDBusArgument & operator >>(const QDBusArgument &a, ApplicationsList &ap) { + a.beginArray(); + ap.clear(); + Application aplication; + Application * ap_ptr; + while ( !a.atEnd() ) { + a>>aplication; + ap_ptr=new Application(aplication.name); + ap_ptr->alerts=aplication.alerts; + ap.insert(aplication.name,QSharedPointer(ap_ptr)); + } + a.endArray(); + return a; +} + +QDBusArgument &operator<<(QDBusArgument &a, const Application &ap){ + a.beginStructure(); + a<>(const QDBusArgument &a, Application &ap) { + a.beginStructure(); + a>>ap.name; + a>>ap.alerts; + a.endStructure(); + return a; +} + +QDBusArgument &operator<<(QDBusArgument &a, const Alert &al){ + a.beginStructure(); + a<>(const QDBusArgument &a, Alert &al) { + a.beginStructure(); + a>>al.name; + a>>al.title; + a>>al.active; + a.endStructure(); + return a; +} + +QDBusArgument &operator<<(QDBusArgument &a, const AlertList &al){ + a.beginArray(qMetaTypeId()); + foreach(QSharedPointer alls,al.values()){ + a<<*alls.data(); + } + a.endArray(); + return a; +} +const QDBusArgument & operator >>(const QDBusArgument &a, AlertList &al) { + a.beginArray(); + al.clear(); + Alert alert; + while ( !a.atEnd() ) { + a>>alert; + al.insert(alert.name,QSharedPointer(new Alert(alert.name,alert.title,alert.active))); + } + a.endArray(); + return a; +} + +#include "dbusbinding.moc" diff --git a/src/plugins/dbusbinding/dbusbinding.h b/src/plugins/dbusbinding/dbusbinding.h new file mode 100644 index 0000000..4fed1f7 --- /dev/null +++ b/src/plugins/dbusbinding/dbusbinding.h @@ -0,0 +1,63 @@ +#ifndef DBUSBINDING_H +#define DBUSBINDING_H +#include +#include "core/interface.h" +#include "core/application.h" +#include "core/snoreserver.h" + +class DBusPlugin:public QObject,SnorePlugin{ + Q_OBJECT + Q_INTERFACES(SnorePlugin) +public: + DBusPlugin(){ + setProperty("name","DbusBinding"); + }; + void setSnore(SnoreServer *snore); + +}; + +class DBusBinding: public QDBusAbstractAdaptor{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "org.SnoreNotify") +public: + DBusBinding(DBusPlugin* db,SnoreServer* snore); + ~DBusBinding(); + static void registerTypes(); +private: + QPointer snore; + +public slots: + ApplicationsList getApplicationList(); + void setAlertActive(const QString &application,const QString &alert,const bool active); + +signals: + void applicationListChanged(const ApplicationsList &); + +private slots: + void applicationListChangedSlot(); + +}; + + +Q_DECLARE_METATYPE(ApplicationsList); +QDBusArgument &operator<<(QDBusArgument &a, const ApplicationsList &ap); +const QDBusArgument & operator >>(const QDBusArgument &a, ApplicationsList &ap) ; + +Q_DECLARE_METATYPE(Application); +QDBusArgument &operator<<(QDBusArgument &a, const Application &ap); +const QDBusArgument & operator >>(const QDBusArgument &a, Application &ap) ; + +Q_DECLARE_METATYPE(Alert); +QDBusArgument &operator<<(QDBusArgument &a, const Alert &al); +const QDBusArgument & operator >>(const QDBusArgument &a, Alert &al) ; + +Q_DECLARE_METATYPE(AlertList); +QDBusArgument &operator<<(QDBusArgument &a, const AlertList &al); +const QDBusArgument & operator >>(const QDBusArgument &a, AlertList &al) ; + + + + + + +#endif // DBUSBINDING_H diff --git a/src/plugins/freedesktopfrontend/CMakeLists.txt b/src/plugins/freedesktopfrontend/CMakeLists.txt new file mode 100644 index 0000000..0f56e13 --- /dev/null +++ b/src/plugins/freedesktopfrontend/CMakeLists.txt @@ -0,0 +1,17 @@ +if(QT_QTDBUS_FOUND) + message(STATUS "Adding freedesktop notification frontend") + + set ( FREEDESKTOP_NOTIFICATION_FRONTEND_SRC + freedesktopnotificationfrontend.cpp + ../freedesktopnotification/fredesktopnotification.cpp + ) + + qt4_add_dbus_adaptor( FREEDESKTOP_NOTIFICATION_FRONTEND_SRC org.freedesktop.Notifications.xml freedesktopnotificationfrontend.h FreedesktopNotification_Frontend) + + automoc4_add_library(freedesktop_frontend MODULE ${FREEDESKTOP_NOTIFICATION_FRONTEND_SRC} ) + target_link_libraries(freedesktop_frontend snore ${QT_QTDBUS_LIBRARY} ${QT_QTGUI_LIBRARY} ) + +endif(QT_QTDBUS_FOUND) + + + diff --git a/src/plugins/freedesktopfrontend/freedesktopnotificationfrontend.cpp b/src/plugins/freedesktopfrontend/freedesktopnotificationfrontend.cpp new file mode 100644 index 0000000..3415305 --- /dev/null +++ b/src/plugins/freedesktopfrontend/freedesktopnotificationfrontend.cpp @@ -0,0 +1,104 @@ +#include "freedesktopnotificationfrontend.h" +#include "notificationsadaptor.h" +#include +#include +#include +#include "plugins/freedesktopnotification/fredesktopnotification.h" +#include "core/snoreserver.h" + +Q_EXPORT_PLUGIN2(freedesktop_frontend,FreedesktopNotification_Frontend) + +FreedesktopNotification_Frontend::FreedesktopNotification_Frontend(){ + setProperty("name","FreedesktopNotification_Frontend"); + new NotificationsAdaptor(this); + QDBusConnection dbus = QDBusConnection::sessionBus(); + dbus.registerService( "org.freedesktop.Notifications" ); + dbus.registerObject( "/org/freedesktop/Notifications", this ); +} + +FreedesktopNotification_Frontend::~FreedesktopNotification_Frontend(){ + QDBusConnection dbus = QDBusConnection::sessionBus(); + dbus.unregisterService( "org.freedesktop.Notifications" ); +} + +void FreedesktopNotification_Frontend::actionInvoked(QSharedPointernotification){ + emit ActionInvoked(notification->id,QString::number(notification->actionInvoked)); +} + +void FreedesktopNotification_Frontend::notificationClosed(QSharedPointernotification){ + uint reason; + switch(notification->actionInvoked){ + case Notification::TIMED_OUT: + reason=1; + break; + case Notification::ACTION_1: + case Notification::ACTION_2: + case Notification::ACTION_3: + reason=2; + break; + default: + reason=4; + } + + emit NotificationClosed(notification->id,reason); +} + +QString FreedesktopNotification_Frontend::getImagefromHint(const FreedesktopImageHint &img){ + QCryptographicHash hash(QCryptographicHash::Md5); + hash.addData(img.imageData); + QString filename=SnoreServer::snoreTMP+hash.result().toHex()+".png"; + QFile file(filename); + if(file.exists())return filename; + + QImage qimage=img.toQImage(); + qimage.save(filename,"PNG"); + qDebug()<<"Saving to "<()>>image; + icon=getImagefromHint(image); + } + QSharedPointer noti(new Notification(property("name").value(),summary,body,icon,timeout)); + noti->id=replaces_id; + return getSnore()->broadcastNotification(noti); +} + + + +void FreedesktopNotification_Frontend::CloseNotification(uint id){ + QSharedPointer n(new Notification()); + n->id=id; + getSnore()->closeNotification(n); +} + +QStringList FreedesktopNotification_Frontend::GetCapabilities() +{ + return QStringList() + << "body" + // << "body-hyperlinks" + // << "body-markup" + << "icon-static" + << "actions" + ; +} + +QString FreedesktopNotification_Frontend::GetServerInformation(QString& vendor, QString& version, QString& specVersion) +{ + vendor = "SnoreNotify"; + version = "0.01"; + specVersion = "0"; + return "SnoreNotify"; +} + + +#include "freedesktopnotificationfrontend.moc" diff --git a/src/plugins/freedesktopfrontend/freedesktopnotificationfrontend.h b/src/plugins/freedesktopfrontend/freedesktopnotificationfrontend.h new file mode 100644 index 0000000..53df973 --- /dev/null +++ b/src/plugins/freedesktopfrontend/freedesktopnotificationfrontend.h @@ -0,0 +1,34 @@ +#ifndef FREEDESKTOPNOTIFICATION_FRONTEND_H +#define FREEDESKTOPNOTIFICATION_FRONTEND_H +#include "core/interface.h" +#include + +class FreedesktopNotification_Frontend:public QObject,Notification_Frontend{ + Q_OBJECT + Q_INTERFACES(Notification_Frontend) +public: + FreedesktopNotification_Frontend(); + ~FreedesktopNotification_Frontend(); + + QString getImagefromHint(const class FreedesktopImageHint &img); + + void actionInvoked(QSharedPointernotification); + void notificationClosed(QSharedPointernotification); + + uint Notify(const QString &app_name, uint replaces_id, const QString &app_icon, const QString &summary, const QString &body, const QStringList &actions, const QVariantMap &hints, int timeout); + + void CloseNotification( uint id ); + + QStringList GetCapabilities(); + + QString GetServerInformation(QString& vendor, QString& version, QString& specVersion); + +signals: + void NotificationClosed( uint id, uint reason ); + void ActionInvoked( uint id, const QString& actionKey ); + + + +}; + +#endif//FREEDESKTOPNOTIFICATION_FRONTEND_H diff --git a/src/plugins/freedesktopfrontend/org.freedesktop.Notifications.xml b/src/plugins/freedesktopfrontend/org.freedesktop.Notifications.xml new file mode 100644 index 0000000..8ddb421 --- /dev/null +++ b/src/plugins/freedesktopfrontend/org.freedesktop.Notifications.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/freedesktopnotification/CMakeLists.txt b/src/plugins/freedesktopnotification/CMakeLists.txt new file mode 100644 index 0000000..641cbab --- /dev/null +++ b/src/plugins/freedesktopnotification/CMakeLists.txt @@ -0,0 +1,12 @@ +if(QT_QTDBUS_FOUND) + message(STATUS "Adding Freedesktop notification backend") + set ( FREEDESKTOP_NOTIFICATION_SRC + freedesktopnotification_backend.cpp + fredesktopnotification.cpp + ) + automoc4_add_library(freedesktop_backend MODULE ${FREEDESKTOP_NOTIFICATION_SRC} ) + target_link_libraries(freedesktop_backend snore ${QT_QTGUI_LIBRARY} ${QT_QTDBUS_LIBRARY} ) +else(QT_QTDBUS_FOUND) + message(STATUS "Adding Freedesktop notification backend.... for Freedesktop notification backend support QDBus is needed") +endif(QT_QTDBUS_FOUND) + diff --git a/src/plugins/freedesktopnotification/fredesktopnotification.cpp b/src/plugins/freedesktopnotification/fredesktopnotification.cpp new file mode 100644 index 0000000..cf9d345 --- /dev/null +++ b/src/plugins/freedesktopnotification/fredesktopnotification.cpp @@ -0,0 +1,78 @@ +#include "fredesktopnotification.h" +#include + +FreedesktopNotification::FreedesktopNotification(){ + registerTypes(); +} + +FreedesktopNotification::FreedesktopNotification(Notification *noti):notification(noti){ + registerTypes(); +} + +void FreedesktopNotification::registerTypes(){ + qDBusRegisterMetaType(); + qDBusRegisterMetaType(); +} + +QDBusArgument &operator<<(QDBusArgument &a, const FreedesktopNotification &i){ + QStringList actions; + actions<<"1"<<" "<<"2"<<" "; + a<app<getIcon()<title<text<getIcon()); + if(!img.isNull()){ + img=img.scaledToWidth(50,Qt::FastTransformation); + a.beginMapEntry(); + a<<"image_data"; + a<timeout*1000; + return a; +} + +const QDBusArgument & operator >>(const QDBusArgument &a, FreedesktopNotification &i){ +//not supported + return a; +} + + +FreedesktopImageHint::FreedesktopImageHint(){ + FreedesktopNotification::registerTypes(); +} + + + +FreedesktopImageHint::FreedesktopImageHint(const QImage &img){ + FreedesktopNotification::registerTypes(); + QImage image(img.convertToFormat(QImage::Format_ARGB32)); + width=image.width(); + height=image.height(); + rowstride=image.bytesPerLine(); + hasAlpha=image.hasAlphaChannel(); + channels =image.isGrayscale()?1:hasAlpha?4:3; + bitsPerSample=image.depth()/channels; + this->imageData.append((char*)image.rgbSwapped().bits(),image.numBytes()); +} + + +QImage FreedesktopImageHint::toQImage()const{ + return QImage((uchar*)imageData.data(),width,height,QImage::Format_ARGB32 ).rgbSwapped(); +} + +QDBusArgument &operator<<(QDBusArgument &a, const FreedesktopImageHint &i) { + a.beginStructure(); + a << i.width<>(const QDBusArgument &a, FreedesktopImageHint &i) { + a.beginStructure(); + a >> i.width>> i.height>> i.rowstride>> i.hasAlpha>> i.bitsPerSample>> i.channels>> i.imageData; + a.endStructure(); + return a; +} + +#include "fredesktopnotification.moc" diff --git a/src/plugins/freedesktopnotification/fredesktopnotification.h b/src/plugins/freedesktopnotification/fredesktopnotification.h new file mode 100644 index 0000000..c15f659 --- /dev/null +++ b/src/plugins/freedesktopnotification/fredesktopnotification.h @@ -0,0 +1,53 @@ +#ifndef FreedesktopNotification_H +#define FreedesktopNotification_H +#include +#include +#include "core/notification.h" +#include + + +class FreedesktopImageHint; + +class FreedesktopNotification{ +public: + static void registerTypes(); + +public: + FreedesktopNotification(); + FreedesktopNotification(Notification *noti); + + QPointer image; + Notification toNotification(); + QPointer notification; + +}; + +Q_DECLARE_METATYPE(FreedesktopNotification); + +QDBusArgument &operator<<(QDBusArgument &a, const FreedesktopNotification &i); +const QDBusArgument & operator >>(const QDBusArgument &a, FreedesktopNotification &i) ; + +class FreedesktopImageHint +{ +public: + FreedesktopImageHint(); + FreedesktopImageHint(const QImage &img); + + QImage toQImage()const; + + int width; + int height; + int rowstride; + bool hasAlpha; + int bitsPerSample; + int channels; + QByteArray imageData; + + +}; +Q_DECLARE_METATYPE(FreedesktopImageHint); + +QDBusArgument &operator<<(QDBusArgument &a, const FreedesktopImageHint &i); +const QDBusArgument & operator >>(const QDBusArgument &a, FreedesktopImageHint &i) ; + +#endif // FreedesktopNotification_H diff --git a/src/plugins/freedesktopnotification/freedesktopnotification_backend.cpp b/src/plugins/freedesktopnotification/freedesktopnotification_backend.cpp new file mode 100644 index 0000000..b3a2798 --- /dev/null +++ b/src/plugins/freedesktopnotification/freedesktopnotification_backend.cpp @@ -0,0 +1,105 @@ +#include "freedesktopnotification_backend.h" +#include +#include "core/notification.h" +#include +#include +#include "fredesktopnotification.h" +#include "core/snoreserver.h" +#include + +Q_EXPORT_PLUGIN2(freedesktopnotificationbackend,FreedesktopNotification_Backend) + +int FreedesktopNotification_Backend::notify( QSharedPointer noti){ + fNotification *n=new fNotification(this); + qDebug()<notification=noti; + return n->send(); +} + +void FreedesktopNotification_Backend::closeNotification(int id){ + //TODO: fix + // fNotification *fn=new fNotification(); + // fn->notification=new Notification(); + // fn->notification->id=id; + // fn->close(); +} + + +QString fNotification::vendor(""); + +QDBusInterface fNotification::notificationInterface("org.freedesktop.Notifications","/org/freedesktop/Notifications","org.freedesktop.Notifications"); + +fNotification::fNotification(FreedesktopNotification_Backend* parent):parent(parent){ + setParent(parent); +} + + + +int fNotification::send(){ + qDebug("Sending a notification"); + FreedesktopNotification n(notification.data()); + QDBusMessage recive=notificationInterface.call("Notify", QVariant::fromValue(n)); + n.notification->id=recive.arguments().last().toInt(); + + selfdistruct.setParent(this); + selfdistruct.setSingleShot(true); + connect(&selfdistruct, SIGNAL(timeout()), this, SLOT(close())); + selfdistruct.start(notification->timeout*1000); + QDBusConnection::sessionBus().connect("org.freedesktop.Notifications","/org/freedesktop/Notifications","org.freedesktop.Notifications","ActionInvoked",this,SLOT(action(uint,QString))); + if(getVendor()=="GNOME") + QDBusConnection::sessionBus().connect("org.freedesktop.Notifications","/org/freedesktop/Notifications","org.freedesktop.Notifications","NotificationClosed",this,SLOT(closed(uint,uint))); + return n.notification->id; +} + +void fNotification::action(const uint &id, const QString &action_key){ + if(id!=notification->id)return; + close(); + qDebug()<actionInvoked=(action_key=="default"?Notification::ACTION_1:Notification::actions(action_key.toInt())); + parent->getSnore()->notificationActionInvoked(notification); + selfDelete(); +} +void fNotification::closed(const uint &id,const uint &reason){ + qDebug()<id)return; + close(); + if(reason==1) + notification->actionInvoked=Notification::TIMED_OUT; + if(reason==2) + notification->actionInvoked=Notification::CLOSED; + parent->getSnore()->closeNotification(notification); + selfDelete(); +} + + + +void fNotification::close(){ + blockSignals(true); + if( !selfdistruct.isActive()){ + notification->actionInvoked=Notification::TIMED_OUT; + parent->getSnore()->closeNotification(notification); + selfDelete(); + } + selfdistruct.stop(); +} + +QString fNotification::getVendor(){ + if(vendor==""){ + QDBusMessage recive= notificationInterface.call(QDBus::AutoDetect,"GetServerInformation"); + vendor=recive.arguments()[1].toString(); + qDebug()< + + +class fNotification; + +class FreedesktopNotification_Backend:public Notification_Backend +{ + Q_OBJECT + Q_INTERFACES(Notification_Backend) +public: + FreedesktopNotification_Backend() + { + setProperty("name","FreedesktopNotification_Backend"); + }; + bool isPrimaryNotificationBackend(){return true;} +public slots: + int notify(QSharedPointernotification); + void closeNotification(int id); + +}; + + + + +class fNotification:public QObject{ + Q_OBJECT +public: + static QDBusInterface notificationInterface; +private: + static QString vendor; + +public: + fNotification(FreedesktopNotification_Backend* parent); + int send(); + QSharedPointer notification; + +private: + Notification_Backend* parent; + QString getVendor(); + QTimer selfdistruct; + +private slots: + void action(const uint &id, const QString &action_key); + void closed(const uint &id,const uint &reason); + void close(); + void selfDelete(); +}; + + +#endif // FREEDESKTOPNOTIFICATION_H diff --git a/src/plugins/redirector/CMakeLists.txt b/src/plugins/redirector/CMakeLists.txt new file mode 100644 index 0000000..d9c265d --- /dev/null +++ b/src/plugins/redirector/CMakeLists.txt @@ -0,0 +1,7 @@ +if(WITH_WEBINTERFACE) + set( REDIRECTOR_SRC + redirector.cpp + ) + automoc4_add_library(redirector MODULE ${REDIRECTOR_SRC}) + target_link_libraries(redirector snore webinterface) +endif(WITH_WEBINTERFACE) \ No newline at end of file diff --git a/src/plugins/redirector/redirector.cpp b/src/plugins/redirector/redirector.cpp new file mode 100644 index 0000000..af3b195 --- /dev/null +++ b/src/plugins/redirector/redirector.cpp @@ -0,0 +1,98 @@ +#include "redirector.h" +#include +#include +#include "core/snoreserver.h" +#include "core/notification.h" +#include +#include + +Q_EXPORT_PLUGIN2(redircetor,Redircetor) + + + +Redircetor::Redircetor(){ + setProperty("name","Redircetor"); + WebInterface::getInstance()->publicatePlugin(this); + getArgument.insert("subscribe",SUBSCRIBE); + getArgument.insert("unsubscribe",UNSUBSCRIBE); + getArgument.insert("listsubscibers",LISTSUBSCRIBERS); +} + + +bool Redircetor::parseCommand(QTcpSocket *client, const QString &command){ + QHostAddress addres=client->peerAddress(); + QString out; + qDebug()<<"parsing"; + qDebug()< subscriber(new QTcpSocket); + subscriber->connectToHost(addres,port ,QTcpSocket::ReadWrite); + if(subscriber->waitForConnected()){ + SnoreServer* snore(getSnore()); + foreach(QSharedPointer a,snore->getAplicationList()->values()){ + QString* app=&a->name; + subscriber->write(QString("type=SNP#?version=1.1#?action=register#?app="+*app+"\r\n").toUtf8()); + foreach(const QSharedPointer al,a->alerts.values()){ + subscriber->write(QString("type=SNP#?version=1.1#?action=add_class#?app="+*app+"#?class="+al->name+"#?title="+al->title+"\r\n").toUtf8()); + } + } + subscribers.insert(addres.toString(),subscriber); + out=addres.toString()+" Sucsefully suscribed"; + }else + out="Subscription failed no client running?"; + break; + } + case LISTSUBSCRIBERS: + out+="\nRegistred Subscriber\n"; + foreach(const QString &s,subscribers.keys()){ + out+=s+"\n"; + } + break; + default: + return false; + } + if(!out.isEmpty()){ + client->write(out.toUtf8()); + client->disconnectFromHost(); + client->waitForDisconnected(); + return true; + } + return false; +} +int Redircetor::notify(QSharedPointernotification){ + foreach(QSharedPointer s,subscribers.values()){ + if(s->isWritable()){ + qDebug()<<"Sending to subscriber"<peerAddress(); + s->write((notification->toSnalrString()+"\r\n").toLatin1()); + } + } + return -1; +} +void Redircetor::closeNotification(int nr){ + qWarning()<<"Not supported"; +} + +QString Redircetor::display(){ + return "Subscribe
Unsubscribe

Prints a list of all subscribers
"; +} + +SnoreServer* Redircetor::getSnore(){ + return this->snore.data(); +} +void Redircetor::setSnore(SnoreServer *snore){ + this->WebInterface_Plugin::setSnore(snore); +} + +#include "redirector.moc" diff --git a/src/plugins/redirector/redirector.h b/src/plugins/redirector/redirector.h new file mode 100644 index 0000000..420d4cc --- /dev/null +++ b/src/plugins/redirector/redirector.h @@ -0,0 +1,38 @@ +#ifndef REDIRECTOR_H +#define REDIRECTOR_H +#include "core/interface.h" +#include +#include "webinterface/webinterface.h" + +class Redircetor:public Notification_Backend,WebInterface_Plugin{ + Q_OBJECT + Q_INTERFACES(Notification_Backend WebInterface_Plugin) +public: + static const int port=9887; +public: + Redircetor(); + bool isPrimaryNotificationBackend(){return false;} + QString display(); + bool parseCommand(QTcpSocket *client, const QString &command); + class SnoreServer* getSnore(); + void setSnore(class SnoreServer *snore); + +public slots: + int notify(QSharedPointernotification); + void closeNotification(int nr); + +private: + QHash > subscribers; + QPointer snore; + + enum ARGUMENTS{ + SUBSCRIBE=1, + UNSUBSCRIBE=2, + LISTSUBSCRIBERS=3, + }; + QHash getArgument; + +}; + + +#endif//REDIRECTOR_H diff --git a/src/plugins/registredapps/CMakeLists.txt b/src/plugins/registredapps/CMakeLists.txt new file mode 100644 index 0000000..16a956b --- /dev/null +++ b/src/plugins/registredapps/CMakeLists.txt @@ -0,0 +1,8 @@ +if(WITH_WEBINTERFACE) + set( REGISTREDAPPS_SRC + registredapps.cpp + ) + + automoc4_add_library(registredapps MODULE ${REGISTREDAPPS_SRC} ) + target_link_libraries(registredapps snore webinterface) +endif(WITH_WEBINTERFACE) diff --git a/src/plugins/registredapps/registredapps.cpp b/src/plugins/registredapps/registredapps.cpp new file mode 100644 index 0000000..55741fc --- /dev/null +++ b/src/plugins/registredapps/registredapps.cpp @@ -0,0 +1,38 @@ +#include "registredapps.h" +#include +#include + + +Q_EXPORT_PLUGIN2(registredapps,RegistredApps) + +RegistredApps::RegistredApps(){ + setProperty("name","RegistredApps"); + WebInterface::getInstance()->publicatePlugin(this); +} + +bool RegistredApps::parseCommand(QTcpSocket *client, const QString &command){ + qDebug()<<"Registred apps"; + if(command.toLower()=="overview"){ + QString out; + out+="Registred Applications\n"; + SnoreServer *snore=getSnore(); + foreach(QSharedPointer a,snore->getAplicationList()->values()){ + out+=a->name+"\n"; + out+="Registred alerts of "+a->name+"\t alert\t title \t is Active\n"; + foreach(const QSharedPointer al,a->alerts.values()) + out+=al->name+"\t"+al->title+"\t\t"+(al->active?"true":"false")+"\n"; + } + client->write(out.toUtf8()); + client->disconnectFromHost(); + client->waitForDisconnected(); + return true; + } + return false; +} + +QString RegistredApps::display(){ + return "Overview of Registred applications
"; +} + + +#include "registredapps.moc" diff --git a/src/plugins/registredapps/registredapps.h b/src/plugins/registredapps/registredapps.h new file mode 100644 index 0000000..02edc9d --- /dev/null +++ b/src/plugins/registredapps/registredapps.h @@ -0,0 +1,17 @@ +#ifndef REGISTREDAPPS_H +#define REGISTREDAPPS_H +#include "core/snore_exports.h" +#include "core/interface.h" +#include "webinterface/webinterface.h" +#include + +class RegistredApps:public QObject,WebInterface_Plugin{ + Q_OBJECT + Q_INTERFACES(SnorePlugin WebInterface_Plugin) +public: + RegistredApps(); + bool parseCommand(QTcpSocket *client, const QString &command); + QString display(); + +}; +#endif//REGISTREDAPPS_H diff --git a/src/plugins/snarl/CMakeLists.txt b/src/plugins/snarl/CMakeLists.txt new file mode 100644 index 0000000..850e62e --- /dev/null +++ b/src/plugins/snarl/CMakeLists.txt @@ -0,0 +1,9 @@ +if(WIN32) + message(STATUS "Adding Snarl notification backend") + set( SNARL__SRC + SnarlInterface.cpp + snarl_backend.cpp + ) + automoc4_add_library(snarln_backend MODULE ${SNARL__SRC} ) + target_link_libraries(snarln_backend snore ${QT_QTCORE_LIBRARY} ) +endif(WIN32) diff --git a/src/plugins/snarl/SnarlInterface.cpp b/src/plugins/snarl/SnarlInterface.cpp new file mode 100644 index 0000000..dcc485d --- /dev/null +++ b/src/plugins/snarl/SnarlInterface.cpp @@ -0,0 +1,813 @@ +// About: +// Snarl C++ interface implementation +// To understand what the different functions do and what they return, please +// have a look at the API on http://www.fullphat.net/dev/api.htm. +// Also have a look at mSnarl_i.bas found in the CVS/SVN repository for Snarl. +// +// The functions in SnarlInterface both have ANSI(UTF8) and UNICODE versions. +// If the LPCWSTR (unicode) version of the functions are called, the strings +// are converted to UTF8 by SnarlInterface before sent to Snarl. So using the +// ANSI/UTF8/LPCSTR versions of the functions are faster! +// +// +// Difference to VB implementation: +// Please note that string functions return NULL when they fail and not an +// empty string. So check for NULL... +// Function names doesn't have the pre "sn". +// +// +// Authors: +// Written and maintained by Toke Noer Nøttrup +// Original C++ version by "Whitman" +// +// License etc. : +// Feel free to use this code and class as you see fit. +// If you improve the code, it would be nice of you to take contact to the +// authors, so all can get the benifit. +// +// There is no guarantee that the code is correct or functional. +// USE AT YOUR OWN RISK +//----------------------------------------------------------------------------- + +// History +// 2008/12/31 : Implemented V39 API +// : Moved SnarlInterface into new Snarl namespace and moved enums etc. out of class +// : Added WCHAR overloads for all functions +// 2008/08/27 : Fixed return value of IsMessageVisible and HideMessage (returns false on failure now) +// : Fixed critical error in the new overloaded UpdateMessage() function +// 2008/08/27 : x64 compiler fix +// 2008/08/24 : Renamed all functions to not have prepended "sn". +// : Memory allocation functions added. (Use FreeString to free strings returned by Snarl) +// : Added m_nLastMessageId to the class. (Use GetLastMessageId() to get it) +// : Overloaded a few functions, so one don't have include the message id. (UpdateMessage f.i.) + +// 2008/06/20 : Fixed snShowMessageEx so it actually sends the extended version - oops +// : Fixed compiler warning C4800: forcing value to bool 'true' or 'false' (performance warning) + +// 2008/05/19 : uSend and uSendEx would always set return value to M_OK on successfull call +// 2008/04/14 : Updated to follow (what should be) the final Snarl 2.0 API +// 2008/03/28 : Few fixes for Snarl 2.0 +// 2007/05/23 : snGetGlobalMsg & snGetSnarlWindow made static +// 2007/03/25 : 1.6 RC1 fixup +// 2007/03/04 : Added - snGetAppPath, snGetIconsPath, snGetVersionEx, +// snSetTimeout, uSendEx + + +#include "SnarlInterface.h" +#include + +using namespace Snarl; + + +//----------------------------------------------------------------------------- +// Constructor/Destructor +//----------------------------------------------------------------------------- +SnarlInterface::SnarlInterface() +: m_hwndFrom(NULL), m_nLastMessageId(0) +{ + +} + +SnarlInterface::~SnarlInterface() +{ + +} + + +//----------------------------------------------------------------------------- +// snShowMessage() + +/// Displays a message with Title and Text. Timeout controls how long the +/// message is displayed for (in seconds) (omitting this value means the message +/// is displayed indefinately). IconPath specifies the location of a PNG image +/// which will be displayed alongside the message text. +/// Message Id on success or M_RESULT on failure + +LONG32 SnarlInterface::ShowMessage(LPCSTR szTitle, LPCSTR szText, LONG32 timeout, LPCSTR szIconPath, HWND hWndReply, WPARAM uReplyMsg) +{ + SNARLSTRUCT ss; + ZeroMemory((void*)&ss, sizeof(ss)); + + ss.Cmd = SNARL_SHOW; + StringCbCopyA((LPSTR)&ss.Title, SNARL_STRING_LENGTH, szTitle); + StringCbCopyA((LPSTR)&ss.Text, SNARL_STRING_LENGTH, szText); + StringCbCopyA((LPSTR)&ss.Icon, SNARL_STRING_LENGTH, szIconPath); + ss.Timeout = timeout; + + ss.LngData2 = reinterpret_cast(hWndReply); + ss.Id = static_cast(uReplyMsg); + + m_nLastMessageId = Send(ss); + return m_nLastMessageId; +} + +LONG32 SnarlInterface::ShowMessage(LPCWSTR szTitle, LPCWSTR szText, LONG32 timeout, LPCWSTR szIconPath, HWND hWndReply, WPARAM uReplyMsg) +{ + LPSTR szUTF8Title = WideToUTF8(szTitle); + LPSTR szUTF8Text = WideToUTF8(szText); + LPSTR szUFT8IconPath = WideToUTF8(szIconPath); + + LONG32 result = ShowMessage(szUTF8Title, szUTF8Text, timeout, szUFT8IconPath, hWndReply, uReplyMsg); + + delete [] szUTF8Title; + delete [] szUTF8Text; + delete [] szUFT8IconPath; + + return result; +} + +//----------------------------------------------------------------------------- +// snShowMessageEx() + +/// Displays a notification. This function is identical to snShowMessage() +/// except that Class specifies an alert previously registered with +/// snRegisterAlert() and SoundFile can optionally specify a WAV sound to play +/// when the notification is displayed on screen. + +/// Message Id on success or M_RESULT on failure + +LONG32 SnarlInterface::ShowMessageEx(LPCSTR szClass, LPCSTR szTitle, LPCSTR szText, LONG32 timeout, LPCSTR szIconPath, HWND hWndReply, WPARAM uReplyMsg, LPCSTR szSoundFile) +{ + SNARLSTRUCTEX ssex; + ZeroMemory((void*)&ssex, sizeof(ssex)); + + ssex.Cmd = SNARL_EX_SHOW; + ssex.Timeout = timeout; + ssex.LngData2 = reinterpret_cast(hWndReply); + ssex.Id = static_cast(uReplyMsg); + + StringCbCopyA((LPSTR)&ssex.Class, SNARL_STRING_LENGTH, szClass); + StringCbCopyA((LPSTR)&ssex.Title, SNARL_STRING_LENGTH, szTitle); + StringCbCopyA((LPSTR)&ssex.Text, SNARL_STRING_LENGTH, szText); + StringCbCopyA((LPSTR)&ssex.Icon, SNARL_STRING_LENGTH, szIconPath); + StringCbCopyA((LPSTR)&ssex.Extra, SNARL_STRING_LENGTH, szSoundFile); + + m_nLastMessageId = Send(ssex); + return m_nLastMessageId; +} + +LONG32 SnarlInterface::ShowMessageEx(LPCWSTR szClass, LPCWSTR szTitle, LPCWSTR szText, LONG32 timeout, LPCWSTR szIconPath, HWND hWndReply, WPARAM uReplyMsg, LPCWSTR szSoundFile) +{ + LPSTR szUTF8Class = WideToUTF8(szClass); + LPSTR szUTF8Title = WideToUTF8(szTitle); + LPSTR szUTF8Text = WideToUTF8(szText); + LPSTR szUFT8IconPath = WideToUTF8(szIconPath); + LPSTR szUFT8SoundFile = WideToUTF8(szSoundFile); + + LONG32 result = ShowMessageEx(szUTF8Class, szUTF8Title, szUTF8Text, timeout, szUFT8IconPath, hWndReply, uReplyMsg, szUFT8SoundFile); + + delete [] szUTF8Class; + delete [] szUTF8Title; + delete [] szUTF8Text; + delete [] szUFT8IconPath; + delete [] szUFT8SoundFile; + + return result; +} + +//----------------------------------------------------------------------------- +// snHideMessage() + +/// Hides the notification specified by Id. Id is the value returned by +/// snShowMessage() or snShowMessageEx() when the notification was initially +/// created. This function returns True if the notification was successfully +/// hidden or False otherwise (for example, the notification may no longer exist). + +BOOL SnarlInterface::HideMessage(LONG32 Id) +{ + SNARLSTRUCT ss; + ss.Cmd = SNARL_HIDE; + ss.Id = Id; + + LONG32 n = Send(ss); + return (n == -1 || n == 1) ? TRUE : FALSE; +} + +BOOL SnarlInterface::HideMessage() +{ + return HideMessage(m_nLastMessageId); +} + +//----------------------------------------------------------------------------- +// snIsMessageVisible() + +/// Returns True if the notification specified by Id is still visible, or +/// False if not. Id is the value returned by snShowMessage() or +/// snShowMessageEx() when the notification was initially created. + +BOOL SnarlInterface::IsMessageVisible(LONG32 Id) +{ + SNARLSTRUCT ss; + ss.Cmd = SNARL_IS_VISIBLE; + ss.Id = Id; + + // We are getting -1 when true, checking for 1 just in case. We don't want to return true for the other M_RESULT returns + LONG32 n = Send(ss); + return (n == -1 || n == 1) ? TRUE : FALSE; +} + +BOOL SnarlInterface::IsMessageVisible() +{ + if (m_nLastMessageId == 0) + return FALSE; + + return IsMessageVisible(m_nLastMessageId); +} + +//----------------------------------------------------------------------------- +// snUpdateMessage() + +/// Changes the title and text in the message specified by Id to the values +/// specified by Title and Text respectively. Id is the value returned by +/// snShowMessage() or snShowMessageEx() when the notification was originally +/// created. To change the timeout parameter of a notification, use snSetTimeout() + +M_RESULT SnarlInterface::UpdateMessage(LONG32 id, LPCSTR szTitle, LPCSTR szText, LPCSTR szIconPath) +{ + SNARLSTRUCT ss; + ZeroMemory((void*)&ss, sizeof(ss)); + + ss.Cmd = SNARL_UPDATE; + ss.Id = id; + + StringCbCopyA((LPSTR)&ss.Title, SNARL_STRING_LENGTH, szTitle); + StringCbCopyA((LPSTR)&ss.Text, SNARL_STRING_LENGTH, szText); + StringCbCopyA((LPSTR)&ss.Icon, SNARL_STRING_LENGTH, szIconPath); + + return static_cast(Send(ss)); +} + +M_RESULT SnarlInterface::UpdateMessage(LONG32 id, LPCWSTR szTitle, LPCWSTR szText, LPCWSTR szIconPath) +{ + LPSTR szParam1 = WideToUTF8(szTitle); + LPSTR szParam2 = WideToUTF8(szText); + LPSTR szParam3 = WideToUTF8(szIconPath); + + M_RESULT result = UpdateMessage(id, szParam1, szParam2, szParam3); + + delete [] szParam1; + delete [] szParam2; + delete [] szParam3; + + return result; +} + +M_RESULT SnarlInterface::UpdateMessage(LPCSTR szTitle, LPCSTR szText, LPCSTR szIconPath) +{ + return UpdateMessage(m_nLastMessageId, szTitle, szText, szIconPath); +} + +M_RESULT SnarlInterface::UpdateMessage(LPCWSTR szTitle, LPCWSTR szText, LPCWSTR szIconPath) +{ + return UpdateMessage(m_nLastMessageId, szTitle, szText, szIconPath); +} + +//----------------------------------------------------------------------------- +// snRegisterConfig + +/// Registers an application's configuration interface with Snarl. +/// AppName is the text that's displayed in the Applications list so it should +/// be people friendly ("My cool app" rather than "my_cool_app"). + +M_RESULT SnarlInterface::RegisterConfig(HWND hWnd, LPCSTR szAppName, LONG32 replyMsg) +{ + return RegisterConfig2(hWnd, szAppName, replyMsg, ""); +} + +M_RESULT SnarlInterface::RegisterConfig(HWND hWnd, LPCWSTR szAppName, LONG32 replyMsg) +{ + return RegisterConfig2(hWnd, szAppName, replyMsg, L""); +} + +//----------------------------------------------------------------------------- +// snRegisterConfig2 + +/// Registers an application's configuration interface with Snarl. +/// This function is identical to snRegisterConfig() except that Icon can be +/// used to specify a PNG image which will be displayed against the +/// application's entry in Snarl's Preferences panel. + +M_RESULT SnarlInterface::RegisterConfig2(HWND hWnd, LPCSTR szAppName, LONG32 replyMsg, LPCSTR szIcon) +{ + if (!szAppName || !szIcon) + return M_BAD_POINTER; + + SNARLSTRUCT ss; + + m_hwndFrom = hWnd; + + ss.Cmd = SNARL_REGISTER_CONFIG_WINDOW_2; + ss.LngData2 = reinterpret_cast(hWnd); + ss.Id = replyMsg; + StringCbCopyA((LPSTR)&ss.Title, SNARL_STRING_LENGTH, szAppName); + StringCbCopyA((LPSTR)&ss.Icon, SNARL_STRING_LENGTH, szIcon); + + return static_cast(Send(ss)); +} + +M_RESULT SnarlInterface::RegisterConfig2(HWND hWnd, LPCWSTR szAppName, LONG32 replyMsg, LPCWSTR szIcon) +{ + LPSTR szParam1 = WideToUTF8(szAppName); + LPSTR szParam2 = WideToUTF8(szIcon); + + M_RESULT result = RegisterConfig2(hWnd, szParam1, replyMsg, szParam2); + + delete [] szParam1; + delete [] szParam2; + + return result; +} + + +//----------------------------------------------------------------------------- +// snRevokeConfig + +/// Removes the application previously registered using snRegisterConfig() or +/// snRegisterConfig2(). hWnd should be the same as that used during registration. + +M_RESULT SnarlInterface::RevokeConfig(HWND hWnd) +{ + SNARLSTRUCT ss; + + m_hwndFrom = NULL; + + ss.Cmd = SNARL_REVOKE_CONFIG_WINDOW; + ss.LngData2 = reinterpret_cast(hWnd); + + return static_cast(Send(ss)); +} + + +//----------------------------------------------------------------------------- +// snGetVersion() + +/// Checks if Snarl is currently running and, if it is, retrieves the major and +/// minor release version numbers in Major and Minor respectively. +/// Returns True if Snarl is running, False otherwise. + +BOOL SnarlInterface::GetVersion(WORD* Major, WORD* Minor) +{ + SNARLSTRUCT ss; + ss.Cmd = SNARL_GET_VERSION; + LONG32 versionInfo = Send(ss); + if (versionInfo > 0 && versionInfo != M_FAILED && versionInfo != M_TIMED_OUT) { + *Major = HIWORD(versionInfo); + *Minor = LOWORD(versionInfo); + return TRUE; + } + return FALSE; +} + + +//----------------------------------------------------------------------------- +// snGetVersionEx + +/// Returns the Snarl system version number. This is an integer value which +/// represents the system build number and can be used to identify the specific +/// version of Snarl running + +LONG32 SnarlInterface::GetVersionEx() +{ + SNARLSTRUCT ss; + ss.Cmd = SNARL_GET_VERSION_EX; + return Send(ss); +} + + +//----------------------------------------------------------------------------- +// snSetTimeout() + +/// Sets the timeout of existing notification Id to Timeout seconds. Id is the +/// value returned by snShowMessage() or snShowMessageEx() when the notification +/// was first created. + +M_RESULT SnarlInterface::SetTimeout(LONG32 Id, LONG32 Timeout) +{ + SNARLSTRUCT ss; + ss.Cmd = SNARL_SET_TIMEOUT; + ss.Id = Id; + ss.LngData2 = Timeout; + + return static_cast(Send(ss)); +} + +M_RESULT SnarlInterface::SetTimeout(LONG32 Timeout) +{ + return SetTimeout(m_nLastMessageId, Timeout); +} + +//----------------------------------------------------------------------------- +// snRegisterAlert() + +/// Registers an alert of Class for application AppName which must have previously +/// been registered with either snRegisterConfig() or snRegisterConfig2(). + +M_RESULT SnarlInterface::RegisterAlert(LPCSTR szAppName, LPCSTR szClass) +{ + SNARLSTRUCT ss; + ss.Cmd = SNARL_REGISTER_ALERT; + StringCbCopyA((LPSTR)&ss.Title, SNARL_STRING_LENGTH, szAppName); + StringCbCopyA((LPSTR)&ss.Text, SNARL_STRING_LENGTH, szClass); + + return static_cast(Send(ss)); +} + +M_RESULT SnarlInterface::RegisterAlert(LPCWSTR szAppName, LPCWSTR szClass) +{ + LPSTR szParam1 = WideToUTF8(szAppName); + LPSTR szParam2 = WideToUTF8(szClass); + + M_RESULT result = RegisterAlert(szParam1, szParam2); + + delete [] szParam1; + delete [] szParam2; + + return result; +} + +//----------------------------------------------------------------------------- +// snGetGlobalMsg() + +/// Returns the atom that corresponds to the "SnarlGlobalEvent" registered +/// Windows message. This message is sent by Snarl when it is first starts and +/// when it shuts down. + +LONG32 SnarlInterface::GetGlobalMsg() +{ + return RegisterWindowMessage(SNARL_GLOBAL_MSG); +} + + +//----------------------------------------------------------------------------- +// snGetSnarlWindow + +HWND SnarlInterface::GetSnarlWindow() +{ + return FindWindow(NULL, _T("Snarl")); +} + + +//----------------------------------------------------------------------------- +// snGetAppPath() + +/// Returns a pointer to the path. +/// ** Remember to call FreeString + +LPCTSTR SnarlInterface::GetAppPath() +{ + HWND hWnd = GetSnarlWindow(); + if (hWnd) + { + HWND hWndPath = FindWindowEx(hWnd, 0, _T("static"), NULL); + if (hWndPath) + { + TCHAR strTmp[MAX_PATH] = {0}; + int nReturn = GetWindowText(hWndPath, strTmp, MAX_PATH); + if (nReturn > 0) { + TCHAR* strReturn = AllocateString(nReturn + 1); + StringCchCopy(strReturn, nReturn + 1, strTmp); + return strReturn; + } + } + } + return NULL; +} + + +//----------------------------------------------------------------------------- +// snGetIconsPath() + +/// Returns a pointer to the iconpath. +/// ** Remember to call FreeString when done with the string + +LPCTSTR SnarlInterface::GetIconsPath() +{ + TCHAR* szIconPath = NULL; + LPCTSTR szPath = GetAppPath(); + if (!szPath) + return NULL; + + size_t nLen = 0; + if (SUCCEEDED(StringCbLength(szPath, MAX_PATH, &nLen))) + { + nLen += 10 + 1; // etc\\icons\\ + NULL + szIconPath = AllocateString(nLen); + + StringCbCopy(szIconPath, nLen * sizeof(TCHAR), szPath); + StringCbCat(szIconPath, nLen * sizeof(TCHAR), _T("etc\\icons\\")); + } + + FreeString(szPath); + + return szIconPath; +} + + +//----------------------------------------------------------------------------- +// snSetAsSnarlApp() + +/// Identifies an application as a Snarl App. (V39) + +void SnarlInterface::SetAsSnarlApp(HWND hWndOwner, SNARL_APP_FLAGS Flags) +{ + if (IsWindow(hWndOwner)) { + SetProp(hWndOwner, _T("snarl_app"), reinterpret_cast(1)); + SetProp(hWndOwner, _T("snarl_app_flags"), reinterpret_cast(Flags)); + } +} + + +//----------------------------------------------------------------------------- +// snGetAppMsg() + +/// Returns the global Snarl Application message (V39) + +LONG32 SnarlInterface::GetAppMsg() +{ + return RegisterWindowMessage(SNARL_APP_MSG); +} + + +//----------------------------------------------------------------------------- +// snRegisterApp() + +/// Registers an application with Snarl (V39) + +M_RESULT SnarlInterface::RegisterApp(LPCSTR Application, LPCSTR SmallIcon, LPCSTR LargeIcon, HWND hWnd, LONG32 ReplyMsg) +{ + m_hwndFrom = hWnd; + + SNARLSTRUCT ss; + ss.Cmd = SNARL_REGISTER_APP; + + StringCbCopyA((LPSTR)&ss.Title, SNARL_STRING_LENGTH, Application); + StringCbCopyA((LPSTR)&ss.Icon, SNARL_STRING_LENGTH, SmallIcon); + StringCbCopyA((LPSTR)&ss.Text, SNARL_STRING_LENGTH, LargeIcon); + + ss.LngData2 = reinterpret_cast(hWnd); + ss.Id = ReplyMsg; + ss.Timeout = GetCurrentProcessId(); + + return static_cast(Send(ss)); +} + +M_RESULT SnarlInterface::RegisterApp(LPCWSTR Application, LPCWSTR SmallIcon, LPCWSTR LargeIcon, HWND hWnd, LONG32 ReplyMsg) +{ + LPSTR szParam1 = WideToUTF8(Application); + LPSTR szParam2 = WideToUTF8(SmallIcon); + LPSTR szParam3 = WideToUTF8(LargeIcon); + + M_RESULT result = RegisterApp(szParam1, szParam2, szParam3, hWnd, ReplyMsg); + + delete [] szParam1; + delete [] szParam2; + delete [] szParam3; + + return result; +} + + +//----------------------------------------------------------------------------- +// snUnregisterApp() + +/// Unregisters an application with Snarl (V39) + +M_RESULT SnarlInterface::UnregisterApp() +{ + SNARLSTRUCT ss; + ss.Cmd = SNARL_UNREGISTER_APP; + ss.LngData2 = GetCurrentProcessId(); + + m_hwndFrom = NULL; + + return static_cast(Send(ss)); +} + + +//----------------------------------------------------------------------------- +// snShowNotification() + +/// Displays a Snarl notification using registered class (V39) +/// Message Id on success or M_RESULT on failure + +LONG32 SnarlInterface::ShowNotification(LPCSTR Class, LPCSTR Title, LPCSTR Text, LONG32 Timeout, LPCSTR Icon, HWND hWndReply, LONG32 uReplyMsg, LPCSTR Sound) +{ + SNARLSTRUCTEX ssex; + ssex.Cmd = SNARL_SHOW_NOTIFICATION; + + StringCbCopyExA((LPSTR)&ssex.Title, SNARL_STRING_LENGTH, Title, NULL, NULL, STRSAFE_IGNORE_NULLS); + StringCbCopyExA((LPSTR)&ssex.Text, SNARL_STRING_LENGTH, Text, NULL, NULL, STRSAFE_IGNORE_NULLS); + StringCbCopyExA((LPSTR)&ssex.Icon, SNARL_STRING_LENGTH, Icon, NULL, NULL, STRSAFE_IGNORE_NULLS); + + ssex.Timeout = Timeout; + ssex.LngData2 = reinterpret_cast(hWndReply); + ssex.Id = uReplyMsg; + + StringCbCopyExA((LPSTR)&ssex.Extra, SNARL_STRING_LENGTH, Sound, NULL, NULL, STRSAFE_IGNORE_NULLS); + StringCbCopyA((LPSTR)&ssex.Class, SNARL_STRING_LENGTH, Class); + + ssex.Reserved1 = GetCurrentProcessId(); + + m_nLastMessageId = Send(ssex); + return m_nLastMessageId; +} + +LONG32 SnarlInterface::ShowNotification(LPCWSTR Class, LPCWSTR Title, LPCWSTR Text, LONG32 Timeout, LPCWSTR Icon, HWND hWndReply, LONG32 uReplyMsg, LPCWSTR Sound) +{ + LPSTR szParam1 = WideToUTF8(Class); + LPSTR szParam2 = WideToUTF8(Title); + LPSTR szParam3 = WideToUTF8(Text); + LPSTR szParam4 = WideToUTF8(Icon); + LPSTR szParam5 = WideToUTF8(Sound); + + LONG32 result = ShowNotification(szParam1, szParam2, szParam3, Timeout, szParam4, hWndReply, uReplyMsg, szParam5); + + delete [] szParam1; + delete [] szParam2; + delete [] szParam3; + delete [] szParam4; + delete [] szParam5; + + return result; +} + + +//----------------------------------------------------------------------------- +// snChangeAttribute() + +/// (V39) + +M_RESULT SnarlInterface::ChangeAttribute(LONG32 Id, SNARL_ATTRIBUTES Attr, LPCSTR Value) +{ + SNARLSTRUCT ss; + ss.Cmd = SNARL_CHANGE_ATTR; + ss.Id = Id; + ss.LngData2 = Attr; + + StringCbCopyExA((LPSTR)&ss.Text, SNARL_STRING_LENGTH, Value, NULL, NULL, STRSAFE_IGNORE_NULLS); + + return static_cast(Send(ss)); +} + +M_RESULT SnarlInterface::ChangeAttribute(LONG32 Id, SNARL_ATTRIBUTES Attr, LPCWSTR Value) +{ + LPSTR szParam1 = WideToUTF8(Value); + + M_RESULT result = ChangeAttribute(Id, Attr, szParam1); + + delete [] szParam1; + + return result; +} + +M_RESULT SnarlInterface::ChangeAttribute(SNARL_ATTRIBUTES Attr, LPCSTR Value) +{ + return ChangeAttribute(m_nLastMessageId, Attr, Value); +} + +M_RESULT SnarlInterface::ChangeAttribute(SNARL_ATTRIBUTES Attr, LPCWSTR Value) +{ + return ChangeAttribute(m_nLastMessageId, Attr, Value); +} + + +//----------------------------------------------------------------------------- +// snSetClassDefault() + +/// Sets the default value for an alert class (V39) + +M_RESULT SnarlInterface::SetClassDefault(LPCSTR Class, SNARL_ATTRIBUTES Attr, LPCSTR Value) +{ + SNARLSTRUCT ss; + ss.Cmd = SNARL_SET_CLASS_DEFAULT; + ss.LngData2 = Attr; + ss.Timeout = GetCurrentProcessId(); + + StringCbCopyExA((LPSTR)&ss.Text, SNARL_STRING_LENGTH, Class, NULL, NULL, STRSAFE_IGNORE_NULLS); + StringCbCopyExA((LPSTR)&ss.Icon, SNARL_STRING_LENGTH, Value, NULL, NULL, STRSAFE_IGNORE_NULLS); + + return static_cast(Send(ss)); +} + +M_RESULT SnarlInterface::SetClassDefault(LPCWSTR Class, SNARL_ATTRIBUTES Attr, LPCWSTR Value) +{ + LPSTR szParam1 = WideToUTF8(Class); + LPSTR szParam2 = WideToUTF8(Value); + + M_RESULT result = SetClassDefault(szParam1, Attr, szParam2); + + delete [] szParam1; + delete [] szParam2; + + return result; +} + + +//----------------------------------------------------------------------------- +// snGetRevision() + +/// Gets the current Snarl revision (build) number (V39) +/// Returns the build version number, or M_RESULT on failure. + +LONG32 SnarlInterface::GetRevision() +{ + SNARLSTRUCT ss; + ss.Cmd = SNARL_GET_REVISION; + ss.LngData2 = 0xFFFE; + + return Send(ss); +} + + +//----------------------------------------------------------------------------- +// snAddClass() + +/// (V39) + +M_RESULT SnarlInterface::AddClass(LPCSTR Class, LPCSTR Description, SNARL_CLASS_FLAGS Flags, LPCSTR DefaultTitle, LPCSTR DefaultIcon, LONG32 DefaultTimeout) +{ + SNARLSTRUCT ss; + ss.Cmd = SNARL_ADD_CLASS; + ss.LngData2 = Flags; + ss.Timeout = GetCurrentProcessId(); + + StringCbCopyExA((LPSTR)&ss.Text, SNARL_STRING_LENGTH, Class, NULL, NULL, STRSAFE_IGNORE_NULLS); + StringCbCopyExA((LPSTR)&ss.Title, SNARL_STRING_LENGTH, Description, NULL, NULL, STRSAFE_IGNORE_NULLS); + + LONG32 result = Send(ss); + + if (static_cast(result) == M_OK) + { + SetClassDefault(Class, SNARL_ATTRIBUTE_TITLE, DefaultTitle); + SetClassDefault(Class, SNARL_ATTRIBUTE_ICON, DefaultIcon); + if (DefaultTimeout > 0) { + char str[64] = {0}; + StringCbPrintfA((LPSTR)&str, sizeof(str), "%d", DefaultTimeout); + SetClassDefault(Class, SNARL_ATTRIBUTE_TIMEOUT, str); + } + + return M_OK; + } + else + return M_FAILED; +} + +M_RESULT SnarlInterface::AddClass(LPCWSTR Class, LPCWSTR Description, SNARL_CLASS_FLAGS Flags, LPCWSTR DefaultTitle, LPCWSTR DefaultIcon, LONG32 DefaultTimeout) +{ + LPCSTR szClass = WideToUTF8(Class); + LPCSTR szDescription = WideToUTF8(Description); + LPCSTR szDefaultTitle = WideToUTF8(DefaultTitle); + LPCSTR szDefaultIcon = WideToUTF8(DefaultIcon); + + M_RESULT result = AddClass(szClass, szDescription, Flags, szDefaultTitle, szDefaultIcon, DefaultTimeout); + + delete [] szClass; + delete [] szDescription; + delete [] szDefaultTitle; + delete [] szDefaultIcon; + + return result; +} + +//----------------------------------------------------------------------------- +// Private functions +//----------------------------------------------------------------------------- + +template +LONG32 SnarlInterface::Send(T ss) +{ + DWORD_PTR nReturn = M_FAILED; + + HWND hWnd = GetSnarlWindow(); + if (IsWindow(hWnd)) + { + COPYDATASTRUCT cds; + cds.dwData = 2; + cds.cbData = sizeof(ss); + cds.lpData = &ss; + + if (SendMessageTimeout(hWnd, WM_COPYDATA, (WPARAM)m_hwndFrom, (LPARAM)&cds, SMTO_ABORTIFHUNG | SMTO_NOTIMEOUTIFNOTHUNG, 1000, &nReturn) == 0) + { + if (GetLastError() == ERROR_TIMEOUT) + nReturn = M_TIMED_OUT; + } + } + + return static_cast(nReturn); +} + +//----------------------------------------------------------------------------- + +// Remember to : delete [] returned string + +LPSTR SnarlInterface::WideToUTF8(LPCWSTR szWideStr) +{ + if (szWideStr == NULL) + return NULL; + + int nSize = WideCharToMultiByte(CP_UTF8, 0, szWideStr, -1, NULL, 0, NULL, NULL); + LPSTR szUTF8 = new char[nSize]; + WideCharToMultiByte(CP_UTF8, 0, szWideStr, -1, szUTF8, nSize, NULL, NULL); + + return szUTF8; +} diff --git a/src/plugins/snarl/SnarlInterface.h b/src/plugins/snarl/SnarlInterface.h new file mode 100644 index 0000000..137d597 --- /dev/null +++ b/src/plugins/snarl/SnarlInterface.h @@ -0,0 +1,218 @@ +#ifndef SNARL_INTERFACE +#define SNARL_INTERFACE + +#include +#include +#include + + +namespace Snarl { + + static const LPCTSTR SNARL_GLOBAL_MSG = _T("SnarlGlobalEvent"); + static const LPCTSTR SNARL_APP_MSG = _T("SnarlAppMessage"); + + static const int SNARL_STRING_LENGTH = 1024; + static const int SNARL_UNICODE_LENGTH = SNARL_STRING_LENGTH / 2; + + static const LONG32 SNARL_LAUNCHED = 1; // Snarl has just started running + static const LONG32 SNARL_QUIT = 2; // Snarl is about to stop running + static const LONG32 SNARL_ASK_APPLET_VER = 3; // (R1.5) Reserved for future use + static const LONG32 SNARL_SHOW_APP_UI = 4; // (R1.6) Application should show its UI + + static const LONG32 SNARL_NOTIFICATION_CLICKED = 32; // notification was right-clicked by user + static const LONG32 SNARL_NOTIFICATION_TIMED_OUT = 33; + static const LONG32 SNARL_NOTIFICATION_ACK = 34; // notification was left-clicked by user + static const LONG32 SNARL_NOTIFICATION_MENU = 35; // V39 - menu item selected + static const LONG32 SNARL_NOTIFICATION_MIDDLE_BUTTON = 36; // V39 - notification middle-clicked by user + static const LONG32 SNARL_NOTIFICATION_CLOSED = 37; // V39 - user clicked the close gadget + + static const LONG32 SNARL_NOTIFICATION_CANCELLED = SNARL_NOTIFICATION_CLICKED; // Added in R1.6 + + static const DWORD WM_SNARLTEST = WM_USER + 237; // note hardcoded WM_USER value! + + // -------------------------------------------------------------------- + + typedef enum M_RESULT { + M_ABORTED = 0x80000007, + M_ACCESS_DENIED = 0x80000009, + M_ALREADY_EXISTS = 0x8000000C, + M_BAD_HANDLE = 0x80000006, + M_BAD_POINTER = 0x80000005, + M_FAILED = 0x80000008, + M_INVALID_ARGS = 0x80000003, + M_NO_INTERFACE = 0x80000004, + M_NOT_FOUND = 0x8000000B, + M_NOT_IMPLEMENTED = 0x80000001, + M_OK = 0x00000000, + M_OUT_OF_MEMORY = 0x80000002, + M_TIMED_OUT = 0x8000000A + }; + + enum SNARL_COMMANDS { + SNARL_SHOW = 1, + SNARL_HIDE, + SNARL_UPDATE, + SNARL_IS_VISIBLE, + SNARL_GET_VERSION, + SNARL_REGISTER_CONFIG_WINDOW, + SNARL_REVOKE_CONFIG_WINDOW, + + /* R1.6 onwards */ + SNARL_REGISTER_ALERT, + SNARL_REVOKE_ALERT, // for future use + SNARL_REGISTER_CONFIG_WINDOW_2, + SNARL_GET_VERSION_EX, + SNARL_SET_TIMEOUT, + + /* following introduced in Snarl V39 (R2.1) */ + SNARL_SET_CLASS_DEFAULT, + SNARL_CHANGE_ATTR, + SNARL_REGISTER_APP, + SNARL_UNREGISTER_APP, + SNARL_ADD_CLASS, + + /* extended commands (all use SNARLSTRUCTEX) */ + SNARL_EX_SHOW = 0x20, + SNARL_SHOW_NOTIFICATION // V39 + }; + + static const SNARL_COMMANDS SNARL_GET_REVISION = SNARL_REVOKE_ALERT; + + typedef enum SNARL_APP_FLAGS { + SNARL_APP_HAS_PREFS = 1, + SNARL_APP_HAS_ABOUT = 2 + }; + + static const LONG32 SNARL_APP_PREFS = 1; + static const LONG32 SNARL_APP_ABOUT = 2; + + + /* --------------- V39 additions --------------- */ + + /* snAddClass() flags */ + enum SNARL_CLASS_FLAGS { + SNARL_CLASS_ENABLED = 0, + SNARL_CLASS_DISABLED = 1, + SNARL_CLASS_NO_DUPLICATES = 2, // means Snarl will suppress duplicate notifications + SNARL_CLASS_DELAY_DUPLICATES = 4 // means Snarl will suppress duplicate notifications within a pre-set time period + }; + + /* Class attributes */ + typedef enum SNARL_ATTRIBUTES { + SNARL_ATTRIBUTE_TITLE = 1, + SNARL_ATTRIBUTE_TEXT, + SNARL_ATTRIBUTE_ICON, + SNARL_ATTRIBUTE_TIMEOUT, + SNARL_ATTRIBUTE_SOUND, + SNARL_ATTRIBUTE_ACK, // file to run on ACK + SNARL_ATTRIBUTE_MENU + }; + + /* ------------------- end of V39 additions ------------------ */ + + struct SNARLSTRUCT { + SNARL_COMMANDS Cmd; + LONG32 Id; + LONG32 Timeout; + LONG32 LngData2; + char Title[SNARL_STRING_LENGTH]; + char Text[SNARL_STRING_LENGTH]; + char Icon[SNARL_STRING_LENGTH]; + }; + + struct SNARLSTRUCTEX { + SNARL_COMMANDS Cmd; + LONG32 Id; + LONG32 Timeout; + LONG32 LngData2; + char Title[SNARL_STRING_LENGTH]; + char Text[SNARL_STRING_LENGTH]; + char Icon[SNARL_STRING_LENGTH]; + + char Class[SNARL_STRING_LENGTH]; + char Extra[SNARL_STRING_LENGTH]; + char Extra2[SNARL_STRING_LENGTH]; + LONG32 Reserved1; + LONG32 Reserved2; + }; + + + + // ------------------------------------------------------------------------ + // SnarlInterface class definition + // ------------------------------------------------------------------------ + + class SnarlInterface { + public: + SnarlInterface(); + ~SnarlInterface(); + + static HWND GetSnarlWindow(); + static LONG32 GetGlobalMsg(); + + + LPTSTR AllocateString(size_t n) { return new TCHAR[n]; } + void FreeString(LPCTSTR str) { delete [] str; str = NULL; } + + + LONG32 ShowMessage(LPCSTR szTitle, LPCSTR szText, LONG32 timeout = 0, LPCSTR szIconPath = "", HWND hWndReply = NULL, WPARAM uReplyMsg = 0); + LONG32 ShowMessage(LPCWSTR szTitle, LPCWSTR szText, LONG32 timeout = 0, LPCWSTR szIconPath = L"", HWND hWndReply = NULL, WPARAM uReplyMsg = 0); + LONG32 ShowMessageEx(LPCSTR szClass, LPCSTR szTitle, LPCSTR szText, LONG32 timeout = 0, LPCSTR szIconPath = "", HWND hWndReply = NULL, WPARAM uReplyMsg = 0, LPCSTR szSoundFile = ""); + LONG32 ShowMessageEx(LPCWSTR szClass, LPCWSTR szTitle, LPCWSTR szText, LONG32 timeout = 0, LPCWSTR szIconPath = L"", HWND hWndReply = NULL, WPARAM uReplyMsg = 0, LPCWSTR szSoundFile = L""); + + LPCTSTR GetAppPath(); // ** Remember to FreeString when finished with the string ! + LPCTSTR GetIconsPath(); // ** Remember to FreeString when finished with the string ! + + BOOL GetVersion(WORD* Major, WORD* Minor); + LONG32 GetVersionEx(); + BOOL HideMessage(); + BOOL HideMessage(LONG32 Id); + BOOL IsMessageVisible(); + BOOL IsMessageVisible(LONG32 Id); + M_RESULT RegisterAlert(LPCSTR szAppName, LPCSTR szClass); + M_RESULT RegisterAlert(LPCWSTR szAppName, LPCWSTR szClass); + M_RESULT RegisterConfig(HWND hWnd, LPCSTR szAppName, LONG32 replyMsg); + M_RESULT RegisterConfig(HWND hWnd, LPCWSTR szAppName, LONG32 replyMsg); + M_RESULT RegisterConfig2(HWND hWnd, LPCSTR szAppName, LONG32 replyMsg, LPCSTR szIcon); + M_RESULT RegisterConfig2(HWND hWnd, LPCWSTR szAppName, LONG32 replyMsg, LPCWSTR szIcon); + M_RESULT RevokeConfig(HWND hWnd); + M_RESULT SetTimeout(LONG32 Timeout); + M_RESULT SetTimeout(LONG32 Id, LONG32 Timeout); + M_RESULT UpdateMessage(LPCSTR szTitle, LPCSTR szText, LPCSTR szIconPath = ""); + M_RESULT UpdateMessage(LPCWSTR szTitle, LPCWSTR szText, LPCWSTR szIconPath = L""); + M_RESULT UpdateMessage(LONG32 Id, LPCSTR szTitle, LPCSTR szText, LPCSTR szIconPath = ""); + M_RESULT UpdateMessage(LONG32 Id, LPCWSTR szTitle, LPCWSTR szText, LPCWSTR szIconPath = L""); + + /* V39 */ + M_RESULT AddClass(LPCSTR Class, LPCSTR Description = NULL, SNARL_CLASS_FLAGS Flags = SNARL_CLASS_ENABLED, LPCSTR DefaultTitle = NULL, LPCSTR DefaultIcon = NULL, LONG32 DefaultTimeout = 0); + M_RESULT AddClass(LPCWSTR Class, LPCWSTR Description = NULL, SNARL_CLASS_FLAGS Flags = SNARL_CLASS_ENABLED, LPCWSTR DefaultTitle = NULL, LPCWSTR DefaultIcon = NULL, LONG32 DefaultTimeout = 0); + M_RESULT ChangeAttribute(SNARL_ATTRIBUTES Attr, LPCSTR Value); + M_RESULT ChangeAttribute(SNARL_ATTRIBUTES Attr, LPCWSTR Value); + M_RESULT ChangeAttribute(LONG32 Id, SNARL_ATTRIBUTES Attr, LPCSTR Value); + M_RESULT ChangeAttribute(LONG32 Id, SNARL_ATTRIBUTES Attr, LPCWSTR Value); + LONG32 GetAppMsg(); + LONG32 GetRevision(); + + M_RESULT RegisterApp(LPCSTR Application, LPCSTR SmallIcon, LPCSTR LargeIcon, HWND hWnd = 0, LONG32 ReplyMsg = 0); + M_RESULT RegisterApp(LPCWSTR Application, LPCWSTR SmallIcon, LPCWSTR LargeIcon, HWND hWnd = 0, LONG32 ReplyMsg = 0); + void SetAsSnarlApp(HWND hWndOwner, SNARL_APP_FLAGS Flags = (SNARL_APP_FLAGS)(SNARL_APP_HAS_ABOUT | SNARL_APP_HAS_PREFS)); + M_RESULT SetClassDefault(LPCSTR Class, SNARL_ATTRIBUTES Attr, LPCSTR Value); + M_RESULT SetClassDefault(LPCWSTR Class, SNARL_ATTRIBUTES Attr, LPCWSTR Value); + LONG32 ShowNotification(LPCSTR Class, LPCSTR Title = NULL, LPCSTR Text = NULL, LONG32 Timeout = 0, LPCSTR Icon = NULL, HWND hWndReply = NULL, LONG32 uReplyMsg = 0, LPCSTR Sound = NULL); + LONG32 ShowNotification(LPCWSTR Class, LPCWSTR Title = NULL, LPCWSTR Text = NULL, LONG32 Timeout = 0, LPCWSTR Icon = NULL, HWND hWndReply = NULL, LONG32 uReplyMsg = 0, LPCWSTR Sound = NULL); + M_RESULT UnregisterApp(); + + LONG32 GetLastMessageId() { return m_nLastMessageId; } + + private: + template LONG32 Send(T ss); + LPSTR WideToUTF8(LPCWSTR szWideStr); + + LONG32 m_nLastMessageId; + HWND m_hwndFrom; // set during snRegisterConfig() or snRegisterConfig2() + + }; + +} + +#endif // SNARL_INTERFACE diff --git a/src/plugins/snarl/snarl_backend.cpp b/src/plugins/snarl/snarl_backend.cpp new file mode 100644 index 0000000..5cc83dc --- /dev/null +++ b/src/plugins/snarl/snarl_backend.cpp @@ -0,0 +1,37 @@ +#include "snarl_backend.h" +#include + + + +Q_EXPORT_PLUGIN2(snarl_backend,Snarl_Backend) + +Snarl_Backend::Snarl_Backend() +{ + setProperty("name","Snarl_Backend"); + snarlInterface=new Snarl::SnarlInterface(); + qDebug()<<"Initiating Snarl Backend, Snarl version: "<GetVersionExA(); + this->installEventFilter(this); + +} + +int Snarl_Backend::notify(QSharedPointernotification){ + int timeout=notification->timeout>=0?notification->timeout/1000:10; + if(notification->id==0){ + return snarlInterface->ShowMessage(notification->title.toLocal8Bit().data(), notification->text.toLocal8Bit().data(),timeout, notification->getIcon().toLocal8Bit().data()); + }else{ + //update message + snarlInterface->UpdateMessage(LONG32(notification->id),notification->title.toLocal8Bit().data(), notification->text.toLocal8Bit().data(),notification->getIcon().toLocal8Bit().data()); + return notification->id; + } +} + +void Snarl_Backend::closeNotification(int nr){ + snarlInterface->HideMessage(nr); +} +bool Snarl_Backend::eventFilter(QObject *obj, QEvent *event){ + qDebug()<objectName(); + return true; +} + + +#include "snarl_backend.moc" diff --git a/src/plugins/snarl/snarl_backend.h b/src/plugins/snarl/snarl_backend.h new file mode 100644 index 0000000..65ae434 --- /dev/null +++ b/src/plugins/snarl/snarl_backend.h @@ -0,0 +1,27 @@ +#ifndef SNARL_BACKEND_H +#define SNARL_BACKEND_H +#include "core/interface.h" +#include "SnarlInterface.h" + +class Snarl_Backend:public Notification_Backend +{ + Q_OBJECT + Q_INTERFACES(Notification_Backend) +public: + Snarl_Backend(); + bool isPrimaryNotificationBackend(){return true;} + + +protected: + bool eventFilter(QObject *obj, QEvent *event); +private: + Snarl::SnarlInterface *snarlInterface; +public slots: + int notify(QSharedPointernotification); + void closeNotification(int nr); + +}; + + + +#endif // SNARL_BACKEND_H diff --git a/src/plugins/snarlnetwork/CMakeLists.txt b/src/plugins/snarlnetwork/CMakeLists.txt new file mode 100644 index 0000000..541505d --- /dev/null +++ b/src/plugins/snarlnetwork/CMakeLists.txt @@ -0,0 +1,6 @@ +set( SNARL_NETWORK_SRC + snarlnetwork.cpp + parser.cpp + ) +automoc4_add_library(snarlnetwork MODULE ${SNARL_NETWORK_SRC} ) +target_link_libraries(snarlnetwork snore ${QT_QTNETWORK_LIBRARY} ) diff --git a/src/plugins/snarlnetwork/parser.cpp b/src/plugins/snarlnetwork/parser.cpp new file mode 100644 index 0000000..9d93e68 --- /dev/null +++ b/src/plugins/snarlnetwork/parser.cpp @@ -0,0 +1,154 @@ +#include "parser.h" +#include "core/snoreserver.h" +#include "snarlnetwork.h" +#include "core/notification.h" +#include +#include +#include +#include +#include +#include + +Parser::Parser(SnarlNetworkFrontend *snarl):snarl(snarl) +{ + getSnpType.insert("type",TYPE); + getSnpType.insert("app",APP); + getSnpType.insert("version",VERSION); + getSnpType.insert("action",ACTION); + getSnpType.insert("register",REGISTER); + getSnpType.insert("add_class",ADD_CLASS); + getSnpType.insert("notification",NOTIFICATION); + getSnpType.insert("unregister",UNREGISTER); + getSnpType.insert("class",CLASS); + getSnpType.insert("title",TITLE); + getSnpType.insert("text",TEXT); + getSnpType.insert("icon",ICON); + getSnpType.insert("timeout",TIMEOUT); +} + + + SnarlNotification Parser::parse(QString &msg,QTcpSocket* client){ + msg=msg.trimmed(); + + SnarlNotification sNotification; + sNotification.httpClient=false; + sNotification.vailid=true; + sNotification.notification=QSharedPointer(new Notification()); + sNotification.clientSocket=client; + + snpTypes action(ERROR); + if(msg.startsWith("GET ")){ + msg=msg.mid(msg.indexOf("/")+1); + msg=msg.mid(0,msg.indexOf(" ")); + QByteArray dat(QByteArray::fromBase64(msg.toLatin1().data())); + msg=QString(dat); + qDebug()<<"Notification from a browser"<app=value; + break; + case ACTION: + action=getSnpType.value(value); + sNotification.action=value; + break; + case TITLE: + sNotification.notification->title=value; + break; + case TEXT: + sNotification.notification->text=value; + break; + case ICON: + sNotification.notification->setIcon(download(value)); + break; + case CLASS: + sNotification.notification->alert=value; + case TIMEOUT: + sNotification.notification->timeout=value.toInt(); + break; + default: + break; + } + } + + + switch(action){ + case NOTIFICATION: + if(snarl->getSnore()->applicationListConontainsAlert(sNotification.notification->app,sNotification.notification->alert)) + break; + return sNotification; + break; + case ADD_CLASS: + if(sNotification.notification->alert.isEmpty()){ + qDebug()<<"Error registering alert with empty name"; + break; + } + if(sNotification.notification->title.isEmpty()) + sNotification.notification->title = sNotification.notification->alert; + snarl->getSnore()->addAlert(sNotification.notification->app,sNotification.notification->alert,sNotification.notification->title); + break; + case REGISTER: + qDebug()<getSnore()->getAplicationList()->keys(); + if(!snarl->getSnore()->getAplicationList()->contains(sNotification.notification->app)&&!sNotification.notification->app.isEmpty()){ + snarl->getSnore()->addApplication(QSharedPointer(new Application(sNotification.notification->app))); + } + else + qDebug()<app<<"already registred"; + break; + case UNREGISTER: + snarl->getSnore()->removeApplication(sNotification.notification->app); + break; + case ERROR: + default: + sNotification.vailid=false; + break; + } + qDebug()<toSnalrString(); + sNotification.notification->hints.insert("SNaction",sNotification.action); + return sNotification; +} + + QString Parser::download(const QString &address){ + if(address=="") + return ""; + if(address.startsWith("file://")) + return QString(address.mid(7)); + QByteArray arr=address.toUtf8(); + QUrl url=QUrl::fromEncoded(arr); + + QCryptographicHash hash(QCryptographicHash::Md5); + hash.addData(arr); + QString filename=QDir::temp().path()+"/SnoreNotify/"+hash.result().toHex()+address.mid(address.lastIndexOf(".")-1); + QFile file(filename); + if(file.exists()) + return filename; + + QNetworkAccessManager manager; + QEventLoop loop; + QNetworkRequest request(url); + request.setRawHeader("User-Agent", "SnoreNotify"); + QNetworkReply *reply=manager.get(request); + QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit())); + + loop.exec(); + + + file.open(QIODevice::WriteOnly); + file.write(reply->readAll()); + + reply->deleteLater(); + return filename; + + } + + +//#include "parser.moc" diff --git a/src/plugins/snarlnetwork/parser.h b/src/plugins/snarlnetwork/parser.h new file mode 100644 index 0000000..da34858 --- /dev/null +++ b/src/plugins/snarlnetwork/parser.h @@ -0,0 +1,43 @@ +#ifndef PARSER_H +#define PARSER_H +#include +#include +#include "core/notification.h" +#include +#include + + + + +class Parser{ +public: + Parser(class SnarlNetworkFrontend* snarl); + + struct SnarlNotification parse(QString &msg,QTcpSocket* client); + +private: + class SnarlNetworkFrontend *snarl; + QString download(const QString &address); + enum snpTypes{ + TYPE, + APP, + VERSION, + ACTION, + REGISTER, + ADD_CLASS, + NOTIFICATION, + UNREGISTER, + CLASS, + TITLE, + TEXT, + ICON, + TIMEOUT, + ERROR + + }; + + QHash getSnpType; + +}; + +#endif // PARSER_H diff --git a/src/plugins/snarlnetwork/snarlnetwork.cpp b/src/plugins/snarlnetwork/snarlnetwork.cpp new file mode 100644 index 0000000..0105d15 --- /dev/null +++ b/src/plugins/snarlnetwork/snarlnetwork.cpp @@ -0,0 +1,86 @@ +#include "snarlnetwork.h" +#include "core/snoreserver.h" +#include +#include + + +Q_EXPORT_PLUGIN2(snalnetwork,SnarlNetworkFrontend) + +SnarlNetworkFrontend::SnarlNetworkFrontend():parser(this){ + setProperty("name","SnarlNetworkFrontend"); + tcpServer=new QTcpServer(this); + if(!tcpServer->listen(QHostAddress::Any,port)){ + qDebug()<<"The port is already used"; + } + connect(tcpServer, SIGNAL(newConnection()), this, SLOT(handleConnection())); +} + + +void SnarlNetworkFrontend::actionInvoked(QSharedPointernotification){ + //TODO:fix callback + SnarlNotification sn=notifications.value(notification->id); + if(notification->actionInvoked==1) + callback(sn,"SNP/1.1/304/Notification acknowledged/"); + else if(notification->actionInvoked==2) + callback(sn,"SNP/1.1/302/Notification cancelled/"); +} +void SnarlNetworkFrontend::notificationClosed(QSharedPointernotification){ + SnarlNotification sn=notifications.value(notification->id); + if(notification->actionInvoked==Notification::TIMED_OUT) + callback(sn,"SNP/1.1/303/Notification timed out/"); + else + callback(sn,"SNP/1.1/307/Notification closed/"); +} + +void SnarlNetworkFrontend::handleConnection(){ + QTcpSocket *client = tcpServer->nextPendingConnection(); + connect(client,SIGNAL(readyRead()),this,SLOT(handleMessages())); + connect(client,SIGNAL(disconnected()), this, SLOT(deleteLater())); +} + +void SnarlNetworkFrontend::handleMessages(){ + QString out("SNP/1.1/0/OK"); + QTcpSocket *client=qobject_cast(sender()); + QStringList incommings(QString::fromUtf8(client->readAll()).split("\r\n")); + foreach(QString s,incommings){ + SnarlNotification noti=parser.parse(s,client); + notifications.insert(noti.notification->id,noti); + if(!noti.vailid) + continue; + int notificationNR=getSnore()->broadcastNotification(noti.notification); + if(notificationNR!=-1){ + out+="/"+QString::number(notificationNR)+"\r\n"; + }else{ + out+="\r\n"; + } + client->write(out.toUtf8()); + if(noti.httpClient){ + client->disconnectFromHost(); + client->waitForDisconnected(); + } + qDebug()<deleteLater(); +} + +void SnarlNetworkFrontend::callback(const SnarlNotification &sn,QString msg){ + if(sn.clientSocket!=NULL&&!msg.isEmpty()){ + msg+=QString::number(sn.notification->id); + qDebug()<write(msg.toAscii()+"\n"); + sn.clientSocket->flush(); + + if(sn.httpClient){ + sn.clientSocket->waitForBytesWritten(-1); + sn.clientSocket->disconnectFromHost(); + } + } +} + + + +#include "snarlnetwork.moc" diff --git a/src/plugins/snarlnetwork/snarlnetwork.h b/src/plugins/snarlnetwork/snarlnetwork.h new file mode 100644 index 0000000..cac231b --- /dev/null +++ b/src/plugins/snarlnetwork/snarlnetwork.h @@ -0,0 +1,40 @@ +#ifndef SNARLNETWORK_H +#define SNARLNETWORK_H +#include "core/interface.h" +#include "parser.h" + +struct SnarlNotification{ + class QSharedPointer notification; + QString action; + bool httpClient; + bool vailid; + class QPointer clientSocket; +}; + +class SnarlNetworkFrontend:public QObject,Notification_Frontend{ + Q_OBJECT + Q_INTERFACES(Notification_Frontend) + friend class Parser; +public: + static const int port=9887; + +public: + SnarlNetworkFrontend(); + void actionInvoked(QSharedPointernotification); + void notificationClosed(QSharedPointernotification); + +private slots: + void handleConnection(); + void handleMessages(); + void clientDisconnecd(); + +private: + class QTcpServer *tcpServer; + Parser parser; + QHash notifications; + + void callback(const SnarlNotification &sn,QString msg); + +}; + +#endif //SNARLNETWORK_H diff --git a/src/plugins/webposter/CMakeLists.txt b/src/plugins/webposter/CMakeLists.txt new file mode 100644 index 0000000..06d9d1c --- /dev/null +++ b/src/plugins/webposter/CMakeLists.txt @@ -0,0 +1,5 @@ +set( WEBPOSTER_SRC + webposter.cpp + ) +automoc4_add_library(webposter MODULE ${WEBPOSTER_SRC} ) +target_link_libraries(webposter snore ${QT_QTNETWORK_LIBRARY} ) diff --git a/src/plugins/webposter/webposter.cpp b/src/plugins/webposter/webposter.cpp new file mode 100644 index 0000000..6f9c336 --- /dev/null +++ b/src/plugins/webposter/webposter.cpp @@ -0,0 +1,38 @@ +#include "webposter.h" +#include +#include +Q_EXPORT_PLUGIN2(webposter,WebPoster) + +WebPoster::WebPoster():manager(new QNetworkAccessManager(this)){ + setProperty("name","WebPoster"); +} + +int WebPoster::notify(QSharedPointernotification){ + QByteArray byte(notification->toSnalrString().toLatin1().data()); + QUrl url("http://www.pro-zeit.ch/index.php"); + url.addEncodedQueryItem("action","add"); + url.addEncodedQueryItem("data",QUrl::toPercentEncoding(byte.toBase64())); + QNetworkRequest request(url); + request.setRawHeader("User-Agent", "SnoreNotify"); + QNetworkReply *reply=manager->get(request); + connect(reply, SIGNAL(readyRead()), this, SLOT(slotReadyRead())); + return -1; + + +} + +void WebPoster::closeNotification(int id){ +//not supportted +} + +void WebPoster::slotReadyRead(){ + QNetworkReply *reply=qobject_cast(sender()); + qDebug()<url(); + qDebug()<readAll(); + if(reply->errorString()!="Unknown error") + qWarning()<errorString(); + reply->deleteLater(); +} + + +#include "webposter.moc" diff --git a/src/plugins/webposter/webposter.h b/src/plugins/webposter/webposter.h new file mode 100644 index 0000000..c2f420d --- /dev/null +++ b/src/plugins/webposter/webposter.h @@ -0,0 +1,25 @@ +#ifndef WEBPOSTER_H +#define WEBPOSTER_H +#include "core/snore_exports.h" +#include "core/interface.h" +#include + + +class WebPoster: public Notification_Backend{ + Q_OBJECT + Q_INTERFACES(Notification_Backend) +public: + WebPoster(); + bool isPrimaryNotificationBackend(){return false;} + +public slots: + int notify(QSharedPointernotification); + void closeNotification(int id); + +private: + QNetworkAccessManager *manager; +public slots: + void slotReadyRead(); + +}; +#endif//WEBPOSTER_H diff --git a/src/webinterface/CMakeLists.txt b/src/webinterface/CMakeLists.txt new file mode 100644 index 0000000..95428a9 --- /dev/null +++ b/src/webinterface/CMakeLists.txt @@ -0,0 +1,10 @@ +if(WITH_WEBINTERFACE) + message(STATUS "Enabling WebInterface support") + set( WEBINTERFACE_SRC + webinterface.cpp + ) + automoc4_add_library(webinterface SHARED ${WEBINTERFACE_SRC} ) + set_target_properties( webinterface PROPERTIES COMPILE_FLAGS "-DWEBINTERFACE_DLL" ) + target_link_libraries(webinterface snore ${QT_QTNETWORK_LIBRARY} ) +endif(WITH_WEBINTERFACE) + diff --git a/src/webinterface/webinterface.cpp b/src/webinterface/webinterface.cpp new file mode 100644 index 0000000..f1f8aba --- /dev/null +++ b/src/webinterface/webinterface.cpp @@ -0,0 +1,70 @@ +#include "webinterface.h" +#include "core/snoreserver.h" +#include +#include +#include +#include +#include + +QPointer WebInterface::instance=0; + +WebInterface* WebInterface::getInstance(){ + if(instance.isNull()) + instance=new WebInterface(); + return instance.data(); +} + +WebInterface::WebInterface() +{ + tcpServer=new QTcpServer(this); + if(!tcpServer->listen(QHostAddress::Any,port)){ + qDebug()<<"The subscription port is already used"; + } + getArgument.insert("",ROOT); + getArgument.insert("overview",OVERVIEW); + connect(tcpServer, SIGNAL(newConnection()), this, SLOT(handleConnection())); + +} +WebInterface::~WebInterface(){ + qDebug()<<"Unloading Webinterface"; + tcpServer->deleteLater(); +} + +void WebInterface::publicatePlugin(WebInterface_Plugin *plugin){ + webinterfaces.append(plugin); + qDebug()<<"appending Webinterface Plugin"; +} + +void WebInterface::handleConnection(){ + QTcpSocket* client= tcpServer->nextPendingConnection(); + connect(client,SIGNAL(readyRead()),this,SLOT(handleMessages())); +} + +void WebInterface::handleMessages(){ + qDebug()<<"Webinteface"; + QTcpSocket *client= (QTcpSocket*)sender(); + QString in(QString::fromUtf8( client->readAll())); + in=in.mid(in.indexOf("/")+1); + in=in.mid(0,in.indexOf(" ")); + QString out; + qDebug()<parseCommand(client,in.toLower())) + return; + } + out+="SnoreNotify Configuration"; + foreach(WebInterface_Plugin* plugin, webinterfaces) + out.append(plugin->display()); + out+=""; + client->write(out.toUtf8()); + qDebug()<<"Sending over web interface:\n"<disconnectFromHost(); + client->waitForDisconnected(); + +} + + + +#include "webinterface.moc" diff --git a/src/webinterface/webinterface.h b/src/webinterface/webinterface.h new file mode 100644 index 0000000..a582ada --- /dev/null +++ b/src/webinterface/webinterface.h @@ -0,0 +1,56 @@ +#ifndef WEBINTERFACE_H +#define WEBINTERFACE_H +#include +#include +#include +#include "core/application.h" +#include "core/interface.h" + +#ifdef WEBINTERFACE_DLL +# define WEBINTERFACE_EXPORT Q_DECL_EXPORT +#else +# define WEBINTERFACE_EXPORT Q_DECL_IMPORT +#endif + +class WEBINTERFACE_EXPORT WebInterface_Plugin:public SnorePlugin{ +public: + virtual ~WebInterface_Plugin() {} + virtual QString display()=0; + virtual bool parseCommand(QTcpSocket *client,const QString &command)=0; + +}; +Q_DECLARE_INTERFACE(WebInterface_Plugin, + "org.Snore.WebInterface/1.0") + +class WEBINTERFACE_EXPORT WebInterface:public QObject +{ + Q_OBJECT +public: + static const int port=9886; + static WebInterface* getInstance(); +public: + void publicatePlugin(WebInterface_Plugin* plugin); + +public slots: + void handleConnection(); + void handleMessages(); + + + +private: + static QPointer instance; + WebInterface(); + ~WebInterface(); + QList webinterfaces; + QTcpServer *tcpServer; + + enum ARGUMENTS{ + ROOT, + SUBSCRIBE, + UNSUBSCRIBE, + OVERVIEW + }; + QHash getArgument; +}; + +#endif // WEBINTERFACE_H