From c5fdf909744dc3d1b3ead51e6e660ccd03e340b5 Mon Sep 17 00:00:00 2001 From: Rik Veenboer Date: Fri, 22 Mar 2013 19:31:26 +0100 Subject: [PATCH] split in java and c++ parts --- .gitignore | 5 +- cpp/Pipe/.cproject | 154 + cpp/Pipe/.project | 27 + cpp/Pipe/include/strsafe.h | 6611 +++++++++++++++++ cpp/Pipe/src/pipe.c | 262 + cpp/Pipe/src/pipe.h | 109 + cpp/pipe/.cproject | 154 + cpp/pipe/.project | 27 + cpp/pipe/include/strsafe.h | 6611 +++++++++++++++++ cpp/pipe/src/pipe.c | 262 + cpp/pipe/src/pipe.h | 109 + .classpath => java/.classpath | 0 java/.gitignore | 3 + .project => java/.project | 0 build.xml => java/build.xml | 0 lame.exe => java/lame.exe | Bin launch4j.xml => java/launch4j.xml | 0 {lib => java/lib}/commons-cli-1.2.jar | Bin {lib => java/lib}/commons-io-2.4.jar | Bin {lib => java/lib}/jid3lib-0.5.4.jar | Bin {lib => java/lib}/jl1.0.1.jar | Bin .../lib}/ostermillerutils-1.08.01.jar | Bin libgomp-1.dll => java/libgomp-1.dll | Bin libmad.dll => java/libmad.dll | Bin libmp3lame.dll => java/libmp3lame.dll | Bin pipes.dll => java/pipes.dll | Bin play.exe => java/play.exe | Bin pthreadgc2.dll => java/pthreadgc2.dll | Bin sox.exe => java/sox.exe | Bin soxi.exe => java/soxi.exe | Bin {src => java/src}/old/Converter.java | 0 {src => java/src}/old/List.java | 0 {src => java/src}/old/Mp3.java | 0 {src => java/src}/old/Utils.java | 0 {src => java/src}/sound/Consumer.java | 0 {src => java/src}/sound/Format.java | 0 .../src}/sound/GreedyInputStream.java | 0 {src => java/src}/sound/Port.java | 0 {src => java/src}/sound/Producer.java | 0 {src => java/src}/sound/Source.java | 0 {src => java/src}/sound/SoxBuilder.java | 0 {src => java/src}/sound/Stream.java | 0 {src => java/src}/sound/Target.java | 0 {src => java/src}/sound/Test.java | 0 {src => java/src}/sound/Tool.java | 0 {src => java/src}/sound/Transducer.java | 0 {src => java/src}/test/SoundAudit.java | 0 {src => java/src}/test/lines/Main.java | 0 {src => java/src}/test/lines/SourceLine.java | 0 {src => java/src}/test/lines/TargetLine.java | 0 stream.bat => java/stream.bat | 0 stream.exe => java/stream.exe | Bin stream.jar => java/stream.jar | Bin java/txt/keuze.txt | 13 + java/txt/mp3 | 1357 ++++ java/txt/options | 182 + java/txt/short | 1 + java/txt/testfiles.txt | 12 + wget.exe => java/wget.exe | Bin zlib1.dll => java/zlib1.dll | Bin 60 files changed, 15896 insertions(+), 3 deletions(-) create mode 100644 cpp/Pipe/.cproject create mode 100644 cpp/Pipe/.project create mode 100644 cpp/Pipe/include/strsafe.h create mode 100644 cpp/Pipe/src/pipe.c create mode 100644 cpp/Pipe/src/pipe.h create mode 100644 cpp/pipe/.cproject create mode 100644 cpp/pipe/.project create mode 100644 cpp/pipe/include/strsafe.h create mode 100644 cpp/pipe/src/pipe.c create mode 100644 cpp/pipe/src/pipe.h rename .classpath => java/.classpath (100%) create mode 100644 java/.gitignore rename .project => java/.project (100%) rename build.xml => java/build.xml (100%) rename lame.exe => java/lame.exe (100%) rename launch4j.xml => java/launch4j.xml (100%) rename {lib => java/lib}/commons-cli-1.2.jar (100%) rename {lib => java/lib}/commons-io-2.4.jar (100%) rename {lib => java/lib}/jid3lib-0.5.4.jar (100%) rename {lib => java/lib}/jl1.0.1.jar (100%) rename {lib => java/lib}/ostermillerutils-1.08.01.jar (100%) rename libgomp-1.dll => java/libgomp-1.dll (100%) rename libmad.dll => java/libmad.dll (100%) rename libmp3lame.dll => java/libmp3lame.dll (100%) rename pipes.dll => java/pipes.dll (100%) rename play.exe => java/play.exe (100%) rename pthreadgc2.dll => java/pthreadgc2.dll (100%) rename sox.exe => java/sox.exe (100%) rename soxi.exe => java/soxi.exe (100%) rename {src => java/src}/old/Converter.java (100%) rename {src => java/src}/old/List.java (100%) rename {src => java/src}/old/Mp3.java (100%) rename {src => java/src}/old/Utils.java (100%) rename {src => java/src}/sound/Consumer.java (100%) rename {src => java/src}/sound/Format.java (100%) rename {src => java/src}/sound/GreedyInputStream.java (100%) rename {src => java/src}/sound/Port.java (100%) rename {src => java/src}/sound/Producer.java (100%) rename {src => java/src}/sound/Source.java (100%) rename {src => java/src}/sound/SoxBuilder.java (100%) rename {src => java/src}/sound/Stream.java (100%) rename {src => java/src}/sound/Target.java (100%) rename {src => java/src}/sound/Test.java (100%) rename {src => java/src}/sound/Tool.java (100%) rename {src => java/src}/sound/Transducer.java (100%) rename {src => java/src}/test/SoundAudit.java (100%) rename {src => java/src}/test/lines/Main.java (100%) rename {src => java/src}/test/lines/SourceLine.java (100%) rename {src => java/src}/test/lines/TargetLine.java (100%) rename stream.bat => java/stream.bat (100%) rename stream.exe => java/stream.exe (100%) rename stream.jar => java/stream.jar (100%) create mode 100644 java/txt/keuze.txt create mode 100644 java/txt/mp3 create mode 100644 java/txt/options create mode 100644 java/txt/short create mode 100644 java/txt/testfiles.txt rename wget.exe => java/wget.exe (100%) rename zlib1.dll => java/zlib1.dll (100%) diff --git a/.gitignore b/.gitignore index a4bf388..aee64d5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ -/bin -/.settings -/sound +/cpp/Pipe/.settings +/cpp/pipe/.settings diff --git a/cpp/Pipe/.cproject b/cpp/Pipe/.cproject new file mode 100644 index 0000000..7e01e41 --- /dev/null +++ b/cpp/Pipe/.cproject @@ -0,0 +1,154 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cpp/Pipe/.project b/cpp/Pipe/.project new file mode 100644 index 0000000..511c69c --- /dev/null +++ b/cpp/Pipe/.project @@ -0,0 +1,27 @@ + + + Pipe + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.core.ccnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/cpp/Pipe/include/strsafe.h b/cpp/Pipe/include/strsafe.h new file mode 100644 index 0000000..061b3c4 --- /dev/null +++ b/cpp/Pipe/include/strsafe.h @@ -0,0 +1,6611 @@ +/****************************************************************** +* * +* strsafe.h -- This module defines safer C library string * +* routine replacements. These are meant to make C * +* a bit more safe in reference to security and * +* robustness * +* * +* Copyright (c) Microsoft Corp. All rights reserved. * +* * +******************************************************************/ +#ifndef _STRSAFE_H_INCLUDED_ +#define _STRSAFE_H_INCLUDED_ +#pragma once + +#include // for _vsnprintf, _vsnwprintf, getc, getwc +#include // for memset +#include // for va_start, etc. + + +#ifndef _SIZE_T_DEFINED +#ifdef _WIN64 +typedef unsigned __int64 size_t; +#else +typedef __w64 unsigned int size_t; +#endif // !_WIN64 +#define _SIZE_T_DEFINED +#endif // !_SIZE_T_DEFINED + +#if !defined(_WCHAR_T_DEFINED) && !defined(_NATIVE_WCHAR_T_DEFINED) +typedef unsigned short wchar_t; +#define _WCHAR_T_DEFINED +#endif + +#ifndef _HRESULT_DEFINED +#define _HRESULT_DEFINED +typedef long HRESULT; +#endif // !_HRESULT_DEFINED + +#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 + +#ifdef __cplusplus +#define _STRSAFE_EXTERN_C extern "C" +#else +#define _STRSAFE_EXTERN_C extern +#endif + +// If you do not want to use these functions inline (and instead want to link w/ strsafe.lib), then +// #define STRSAFE_LIB before including this header file. +#if defined(STRSAFE_LIB) +#define STRSAFEAPI _STRSAFE_EXTERN_C HRESULT __stdcall +#pragma comment(lib, "strsafe.lib") +#elif defined(STRSAFE_LIB_IMPL) +#define STRSAFEAPI _STRSAFE_EXTERN_C HRESULT __stdcall +#else +#define STRSAFEAPI __inline HRESULT __stdcall +#define STRSAFE_INLINE +#endif + +// Some functions always run inline because they use stdin and we want to avoid building multiple +// versions of strsafe lib depending on if you use msvcrt, libcmt, etc. +#define STRSAFE_INLINE_API __inline HRESULT __stdcall + +// The user can request no "Cb" or no "Cch" fuctions, but not both! +#if defined(STRSAFE_NO_CB_FUNCTIONS) && defined(STRSAFE_NO_CCH_FUNCTIONS) +#error cannot specify both STRSAFE_NO_CB_FUNCTIONS and STRSAFE_NO_CCH_FUNCTIONS !! +#endif + +// This should only be defined when we are building strsafe.lib +#ifdef STRSAFE_LIB_IMPL +#define STRSAFE_INLINE +#endif + + +// If both strsafe.h and ntstrsafe.h are included, only use definitions from one. +#ifndef _NTSTRSAFE_H_INCLUDED_ + +#define STRSAFE_MAX_CCH 2147483647 // max # of characters we support (same as INT_MAX) + +// Flags for controling the Ex functions +// +// STRSAFE_FILL_BYTE(0xFF) 0x000000FF // bottom byte specifies fill pattern +#define STRSAFE_IGNORE_NULLS 0x00000100 // treat null as TEXT("") -- don't fault on NULL buffers +#define STRSAFE_FILL_BEHIND_NULL 0x00000200 // fill in extra space behind the null terminator +#define STRSAFE_FILL_ON_FAILURE 0x00000400 // on failure, overwrite pszDest with fill pattern and null terminate it +#define STRSAFE_NULL_ON_FAILURE 0x00000800 // on failure, set *pszDest = TEXT('\0') +#define STRSAFE_NO_TRUNCATION 0x00001000 // instead of returning a truncated result, copy/append nothing to pszDest and null terminate it + +#define STRSAFE_VALID_FLAGS (0x000000FF | STRSAFE_IGNORE_NULLS | STRSAFE_FILL_BEHIND_NULL | STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION) + +// helper macro to set the fill character and specify buffer filling +#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 // _NTSTRSAFE_H_INCLUDED_ + +// STRSAFE error return codes +// +#define STRSAFE_E_INSUFFICIENT_BUFFER ((HRESULT)0x8007007AL) // 0x7A = 122L = ERROR_INSUFFICIENT_BUFFER +#define STRSAFE_E_INVALID_PARAMETER ((HRESULT)0x80070057L) // 0x57 = 87L = ERROR_INVALID_PARAMETER +#define STRSAFE_E_END_OF_FILE ((HRESULT)0x80070026L) // 0x26 = 38L = ERROR_HANDLE_EOF + +// prototypes for the worker functions +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCopyWorkerA(char* pszDest, size_t cchDest, const char* pszSrc); +STRSAFEAPI StringCopyWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc); +STRSAFEAPI StringCopyExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFEAPI StringCopyExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFEAPI StringCopyNWorkerA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc); +STRSAFEAPI StringCopyNWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchSrc); +STRSAFEAPI StringCopyNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, size_t cchSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFEAPI StringCopyNExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, const wchar_t* pszSrc, size_t cchSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFEAPI StringCatWorkerA(char* pszDest, size_t cchDest, const char* pszSrc); +STRSAFEAPI StringCatWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc); +STRSAFEAPI StringCatExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFEAPI StringCatExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFEAPI StringCatNWorkerA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend); +STRSAFEAPI StringCatNWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchMaxAppend); +STRSAFEAPI StringCatNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, size_t cchMaxAppend, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFEAPI StringCatNExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, const wchar_t* pszSrc, size_t cchMaxAppend, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFEAPI StringVPrintfWorkerA(char* pszDest, size_t cchDest, const char* pszFormat, va_list argList); +STRSAFEAPI StringVPrintfWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszFormat, va_list argList); +STRSAFEAPI StringVPrintfExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList); +STRSAFEAPI StringVPrintfExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const wchar_t* pszFormat, va_list argList); +STRSAFEAPI StringLengthWorkerA(const char* psz, size_t cchMax, size_t* pcch); +STRSAFEAPI StringLengthWorkerW(const wchar_t* psz, size_t cchMax, size_t* pcch); +#endif // STRSAFE_INLINE + +#ifndef STRSAFE_LIB_IMPL +// these functions are always inline +STRSAFE_INLINE_API StringGetsExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFE_INLINE_API StringGetsExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +#endif + +#ifdef _NTSTRSAFE_H_INCLUDED_ +#pragma warning(push) +#pragma warning(disable : 4995) +#endif // _NTSTRSAFE_H_INCLUDED_ + + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI +StringCchCopy( + OUT LPTSTR pszDest, + IN size_t cchDest, + IN LPCTSTR pszSrc + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'strcpy'. + The size of the destination buffer (in characters) is a parameter and + this function will not write past the end of this buffer and it will + ALWAYS null terminate the destination buffer (unless it is zero length). + + This routine is not a replacement for strncpy. That function will pad the + destination string with extra null termination characters if the count is + greater than the length of the source string, and it will fail to null + terminate the destination string if the source string length is greater + than or equal to the count. You can not blindly use this instead of strncpy: + it is common for code to use it to "patch" strings and you would introduce + errors if the code started null terminating in the middle of the string. + + This function returns a hresult, and not a pointer. It returns + S_OK if the string was copied without truncation and null terminated, + otherwise it will return a failure code. In failure cases as much of + pszSrc will be copied to pszDest as possible, and pszDest will be null + terminated. + +Arguments: + + pszDest - destination string + + cchDest - size of destination buffer in characters. + length must be = (_tcslen(src) + 1) to hold all of the + source including the null terminator + + pszSrc - source string which must be null terminated + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL. See StringCchCopyEx if you require + the handling of NULL values. + +Return Value: + + S_OK - if there was source data and it was all copied and the + resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the copy + operation failed due to insufficient space. When this + error occurs, the destination buffer is modified to + contain a truncated version of the ideal result and is + null terminated. This is useful for situations where + truncation is ok + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function. + +--*/ + +STRSAFEAPI StringCchCopyA(char* pszDest, size_t cchDest, const char* pszSrc); +STRSAFEAPI StringCchCopyW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc); +#ifdef UNICODE +#define StringCchCopy StringCchCopyW +#else +#define StringCchCopy StringCchCopyA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCchCopyA(char* pszDest, size_t cchDest, const char* pszSrc) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCopyWorkerA(pszDest, cchDest, pszSrc); + } + + return hr; +} + +STRSAFEAPI StringCchCopyW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCopyWorkerW(pszDest, cchDest, pszSrc); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CCH_FUNCTIONS + + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI +StringCbCopy( + OUT LPTSTR pszDest, + IN size_t cbDest, + IN LPCTSTR pszSrc + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'strcpy'. + The size of the destination buffer (in bytes) is a parameter and this + function will not write past the end of this buffer and it will ALWAYS + null terminate the destination buffer (unless it is zero length). + + This routine is not a replacement for strncpy. That function will pad the + destination string with extra null termination characters if the count is + greater than the length of the source string, and it will fail to null + terminate the destination string if the source string length is greater + than or equal to the count. You can not blindly use this instead of strncpy: + it is common for code to use it to "patch" strings and you would introduce + errors if the code started null terminating in the middle of the string. + + This function returns a hresult, and not a pointer. It returns + S_OK if the string was copied without truncation and null terminated, + otherwise it will return a failure code. In failure cases as much of pszSrc + will be copied to pszDest as possible, and pszDest will be null terminated. + +Arguments: + + pszDest - destination string + + cbDest - size of destination buffer in bytes. + length must be = ((_tcslen(src) + 1) * sizeof(TCHAR)) to + hold all of the source including the null terminator + + pszSrc - source string which must be null terminated + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL. See StringCbCopyEx if you require + the handling of NULL values. + +Return Value: + + S_OK - if there was source data and it was all copied and the + resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the copy + operation failed due to insufficient space. When this + error occurs, the destination buffer is modified to + contain a truncated version of the ideal result and is + null terminated. This is useful for situations where + truncation is ok + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function. + +--*/ + +STRSAFEAPI StringCbCopyA(char* pszDest, size_t cbDest, const char* pszSrc); +STRSAFEAPI StringCbCopyW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc); +#ifdef UNICODE +#define StringCbCopy StringCbCopyW +#else +#define StringCbCopy StringCbCopyA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCbCopyA(char* pszDest, size_t cbDest, const char* pszSrc) +{ + HRESULT hr; + size_t cchDest; + + // convert to count of characters + cchDest = cbDest / sizeof(char); + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCopyWorkerA(pszDest, cchDest, pszSrc); + } + + return hr; +} + +STRSAFEAPI StringCbCopyW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc) +{ + HRESULT hr; + size_t cchDest; + + // convert to count of characters + cchDest = cbDest / sizeof(wchar_t); + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCopyWorkerW(pszDest, cchDest, pszSrc); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CB_FUNCTIONS + + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI +StringCchCopyEx( + OUT LPTSTR pszDest OPTIONAL, + IN size_t cchDest, + IN LPCTSTR pszSrc OPTIONAL, + OUT LPTSTR* ppszDestEnd OPTIONAL, + OUT size_t* pcchRemaining OPTIONAL, + IN DWORD dwFlags + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'strcpy' with + some additional parameters. In addition to functionality provided by + StringCchCopy, this routine also returns a pointer to the end of the + destination string and the number of characters left in the destination string + including the null terminator. The flags parameter allows additional controls. + +Arguments: + + pszDest - destination string + + cchDest - size of destination buffer in characters. + length must be = (_tcslen(pszSrc) + 1) to hold all of + the source including the null terminator + + pszSrc - source string which must be null terminated + + ppszDestEnd - if ppszDestEnd is non-null, the function will return a + pointer to the end of the destination string. If the + function copied any data, the result will point to the + null termination character + + pcchRemaining - if pcchRemaining is non-null, the function will return the + number of characters left in the destination string, + including the null terminator + + dwFlags - controls some details of the string copy: + + STRSAFE_FILL_BEHIND_NULL + if the function succeeds, the low byte of dwFlags will be + used to fill the uninitialize part of destination buffer + behind the null terminator + + STRSAFE_IGNORE_NULLS + treat NULL string pointers like empty strings (TEXT("")). + this flag is useful for emulating functions like lstrcpy + + STRSAFE_FILL_ON_FAILURE + if the function fails, the low byte of dwFlags will be + used to fill all of the destination buffer, and it will + be null terminated. This will overwrite any truncated + string returned when the failure is + STRSAFE_E_INSUFFICIENT_BUFFER + + STRSAFE_NO_TRUNCATION / + STRSAFE_NULL_ON_FAILURE + if the function fails, the destination buffer will be set + to the empty string. This will overwrite any truncated string + returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER. + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag + is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc + may be NULL. An error may still be returned even though NULLS are ignored + due to insufficient space. + +Return Value: + + S_OK - if there was source data and it was all copied and the + resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the copy + operation failed due to insufficient space. When this + error occurs, the destination buffer is modified to + contain a truncated version of the ideal result and is + null terminated. This is useful for situations where + truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCchCopyExA(char* pszDest, size_t cchDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFEAPI StringCchCopyExW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +#ifdef UNICODE +#define StringCchCopyEx StringCchCopyExW +#else +#define StringCchCopyEx StringCchCopyExA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCchCopyExA(char* pszDest, size_t cchDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + + // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1 + cbDest = cchDest * sizeof(char); + + hr = StringCopyExWorkerA(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, pcchRemaining, dwFlags); + } + + return hr; +} + +STRSAFEAPI StringCchCopyExW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + + // safe to multiply cchDest * sizeof(wchar_t) since cchDest < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 + cbDest = cchDest * sizeof(wchar_t); + + hr = StringCopyExWorkerW(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, pcchRemaining, dwFlags); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CCH_FUNCTIONS + + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI +StringCbCopyEx( + OUT LPTSTR pszDest OPTIONAL, + IN size_t cbDest, + IN LPCTSTR pszSrc OPTIONAL, + OUT LPTSTR* ppszDestEnd OPTIONAL, + OUT size_t* pcbRemaining OPTIONAL, + IN DWORD dwFlags + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'strcpy' with + some additional parameters. In addition to functionality provided by + StringCbCopy, this routine also returns a pointer to the end of the + destination string and the number of bytes left in the destination string + including the null terminator. The flags parameter allows additional controls. + +Arguments: + + pszDest - destination string + + cbDest - size of destination buffer in bytes. + length must be ((_tcslen(pszSrc) + 1) * sizeof(TCHAR)) to + hold all of the source including the null terminator + + pszSrc - source string which must be null terminated + + ppszDestEnd - if ppszDestEnd is non-null, the function will return a + pointer to the end of the destination string. If the + function copied any data, the result will point to the + null termination character + + pcbRemaining - pcbRemaining is non-null,the function will return the + number of bytes left in the destination string, + including the null terminator + + dwFlags - controls some details of the string copy: + + STRSAFE_FILL_BEHIND_NULL + if the function succeeds, the low byte of dwFlags will be + used to fill the uninitialize part of destination buffer + behind the null terminator + + STRSAFE_IGNORE_NULLS + treat NULL string pointers like empty strings (TEXT("")). + this flag is useful for emulating functions like lstrcpy + + STRSAFE_FILL_ON_FAILURE + if the function fails, the low byte of dwFlags will be + used to fill all of the destination buffer, and it will + be null terminated. This will overwrite any truncated + string returned when the failure is + STRSAFE_E_INSUFFICIENT_BUFFER + + STRSAFE_NO_TRUNCATION / + STRSAFE_NULL_ON_FAILURE + if the function fails, the destination buffer will be set + to the empty string. This will overwrite any truncated string + returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER. + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag + is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc + may be NULL. An error may still be returned even though NULLS are ignored + due to insufficient space. + +Return Value: + + S_OK - if there was source data and it was all copied and the + resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the copy + operation failed due to insufficient space. When this + error occurs, the destination buffer is modified to + contain a truncated version of the ideal result and is + null terminated. This is useful for situations where + truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCbCopyExA(char* pszDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags); +STRSAFEAPI StringCbCopyExW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags); +#ifdef UNICODE +#define StringCbCopyEx StringCbCopyExW +#else +#define StringCbCopyEx StringCbCopyExA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCbCopyExA(char* pszDest, size_t cbDest, const char* pszSrc, char** 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) + { + // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1 + *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)); + } + } + + return hr; +} + +STRSAFEAPI StringCbCopyExW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, wchar_t** 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) + { + // safe to multiply cchRemaining * sizeof(wchar_t) since cchRemaining < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 + *pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)); + } + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CB_FUNCTIONS + + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI +StringCchCopyN( + OUT LPTSTR pszDest, + IN size_t cchDest, + IN LPCTSTR pszSrc, + IN size_t cchSrc + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'strncpy'. + The size of the destination buffer (in characters) is a parameter and + this function will not write past the end of this buffer and it will + ALWAYS null terminate the destination buffer (unless it is zero length). + + This routine is meant as a replacement for strncpy, but it does behave + differently. This function will not pad the destination buffer with extra + null termination characters if cchSrc is greater than the length of pszSrc. + + This function returns a hresult, and not a pointer. It returns + S_OK if the entire string or the first cchSrc characters were copied + without truncation and the resultant destination string was null terminated, + otherwise it will return a failure code. In failure cases as much of pszSrc + will be copied to pszDest as possible, and pszDest will be null terminated. + +Arguments: + + pszDest - destination string + + cchDest - size of destination buffer in characters. + length must be = (_tcslen(src) + 1) to hold all of the + source including the null terminator + + pszSrc - source string + + cchSrc - maximum number of characters to copy from source string, + not including the null terminator. + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL. See StringCchCopyNEx if you require + the handling of NULL values. + +Return Value: + + S_OK - if there was source data and it was all copied and the + resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the copy + operation failed due to insufficient space. When this + error occurs, the destination buffer is modified to + contain a truncated version of the ideal result and is + null terminated. This is useful for situations where + truncation is ok + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function. + +--*/ + +STRSAFEAPI StringCchCopyNA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc); +STRSAFEAPI StringCchCopyNW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchSrc); +#ifdef UNICODE +#define StringCchCopyN StringCchCopyNW +#else +#define StringCchCopyN StringCchCopyNA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCchCopyNA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc) +{ + HRESULT hr; + + if ((cchDest > STRSAFE_MAX_CCH) || + (cchSrc > STRSAFE_MAX_CCH)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCopyNWorkerA(pszDest, cchDest, pszSrc, cchSrc); + } + + return hr; +} + +STRSAFEAPI StringCchCopyNW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchSrc) +{ + HRESULT hr; + + if ((cchDest > STRSAFE_MAX_CCH) || + (cchSrc > STRSAFE_MAX_CCH)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCopyNWorkerW(pszDest, cchDest, pszSrc, cchSrc); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CCH_FUNCTIONS + + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI +StringCbCopyN( + OUT LPTSTR pszDest, + IN size_t cbDest, + IN LPCTSTR pszSrc, + IN size_t cbSrc + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'strncpy'. + The size of the destination buffer (in bytes) is a parameter and this + function will not write past the end of this buffer and it will ALWAYS + null terminate the destination buffer (unless it is zero length). + + This routine is meant as a replacement for strncpy, but it does behave + differently. This function will not pad the destination buffer with extra + null termination characters if cbSrc is greater than the size of pszSrc. + + This function returns a hresult, and not a pointer. It returns + S_OK if the entire string or the first cbSrc characters were + copied without truncation and the resultant destination string was null + terminated, otherwise it will return a failure code. In failure cases as + much of pszSrc will be copied to pszDest as possible, and pszDest will be + null terminated. + +Arguments: + + pszDest - destination string + + cbDest - size of destination buffer in bytes. + length must be = ((_tcslen(src) + 1) * sizeof(TCHAR)) to + hold all of the source including the null terminator + + pszSrc - source string + + cbSrc - maximum number of bytes to copy from source string, + not including the null terminator. + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL. See StringCbCopyEx if you require + the handling of NULL values. + +Return Value: + + S_OK - if there was source data and it was all copied and the + resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the copy + operation failed due to insufficient space. When this + error occurs, the destination buffer is modified to + contain a truncated version of the ideal result and is + null terminated. This is useful for situations where + truncation is ok + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function. + +--*/ + +STRSAFEAPI StringCbCopyNA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbSrc); +STRSAFEAPI StringCbCopyNW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, size_t cbSrc); +#ifdef UNICODE +#define StringCbCopyN StringCbCopyNW +#else +#define StringCbCopyN StringCbCopyNA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCbCopyNA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbSrc) +{ + HRESULT hr; + size_t cchDest; + size_t cchSrc; + + // convert to count of characters + cchDest = cbDest / sizeof(char); + cchSrc = cbSrc / sizeof(char); + + if ((cchDest > STRSAFE_MAX_CCH) || + (cchSrc > STRSAFE_MAX_CCH)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCopyNWorkerA(pszDest, cchDest, pszSrc, cchSrc); + } + + return hr; +} + +STRSAFEAPI StringCbCopyNW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, size_t cbSrc) +{ + HRESULT hr; + size_t cchDest; + size_t cchSrc; + + // convert to count of characters + cchDest = cbDest / sizeof(wchar_t); + cchSrc = cbSrc / sizeof(wchar_t); + + if ((cchDest > STRSAFE_MAX_CCH) || + (cchSrc > STRSAFE_MAX_CCH)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCopyNWorkerW(pszDest, cchDest, pszSrc, cchSrc); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CB_FUNCTIONS + + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI +StringCchCopyNEx( + OUT LPTSTR pszDest OPTIONAL, + IN size_t cchDest, + IN LPCTSTR pszSrc OPTIONAL, + IN size_t cchSrc, + OUT LPTSTR* ppszDestEnd OPTIONAL, + OUT size_t* pcchRemaining OPTIONAL, + IN DWORD dwFlags + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'strncpy' with + some additional parameters. In addition to functionality provided by + StringCchCopyN, this routine also returns a pointer to the end of the + destination string and the number of characters left in the destination + string including the null terminator. The flags parameter allows + additional controls. + + This routine is meant as a replacement for strncpy, but it does behave + differently. This function will not pad the destination buffer with extra + null termination characters if cchSrc is greater than the length of pszSrc. + +Arguments: + + pszDest - destination string + + cchDest - size of destination buffer in characters. + length must be = (_tcslen(pszSrc) + 1) to hold all of + the source including the null terminator + + pszSrc - source string + + cchSrc - maximum number of characters to copy from the source + string + + ppszDestEnd - if ppszDestEnd is non-null, the function will return a + pointer to the end of the destination string. If the + function copied any data, the result will point to the + null termination character + + pcchRemaining - if pcchRemaining is non-null, the function will return the + number of characters left in the destination string, + including the null terminator + + dwFlags - controls some details of the string copy: + + STRSAFE_FILL_BEHIND_NULL + if the function succeeds, the low byte of dwFlags will be + used to fill the uninitialize part of destination buffer + behind the null terminator + + STRSAFE_IGNORE_NULLS + treat NULL string pointers like empty strings (TEXT("")). + this flag is useful for emulating functions like lstrcpy + + STRSAFE_FILL_ON_FAILURE + if the function fails, the low byte of dwFlags will be + used to fill all of the destination buffer, and it will + be null terminated. This will overwrite any truncated + string returned when the failure is + STRSAFE_E_INSUFFICIENT_BUFFER + + STRSAFE_NO_TRUNCATION / + STRSAFE_NULL_ON_FAILURE + if the function fails, the destination buffer will be set + to the empty string. This will overwrite any truncated string + returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER. + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag + is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc + may be NULL. An error may still be returned even though NULLS are ignored + due to insufficient space. + +Return Value: + + S_OK - if there was source data and it was all copied and the + resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the copy + operation failed due to insufficient space. When this + error occurs, the destination buffer is modified to + contain a truncated version of the ideal result and is + null terminated. This is useful for situations where + truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCchCopyNExA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFEAPI StringCchCopyNExW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +#ifdef UNICODE +#define StringCchCopyNEx StringCchCopyNExW +#else +#define StringCchCopyNEx StringCchCopyNExA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCchCopyNExA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr; + + if ((cchDest > STRSAFE_MAX_CCH) || + (cchSrc > STRSAFE_MAX_CCH)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + + // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1 + cbDest = cchDest * sizeof(char); + + hr = StringCopyNExWorkerA(pszDest, cchDest, cbDest, pszSrc, cchSrc, ppszDestEnd, pcchRemaining, dwFlags); + } + + return hr; +} + +STRSAFEAPI StringCchCopyNExW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr; + + if ((cchDest > STRSAFE_MAX_CCH) || + (cchSrc > STRSAFE_MAX_CCH)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + + // safe to multiply cchDest * sizeof(wchar_t) since cchDest < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 + cbDest = cchDest * sizeof(wchar_t); + + hr = StringCopyNExWorkerW(pszDest, cchDest, cbDest, pszSrc, cchSrc, ppszDestEnd, pcchRemaining, dwFlags); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CCH_FUNCTIONS + + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI +StringCbCopyNEx( + OUT LPTSTR pszDest OPTIONAL, + IN size_t cbDest, + IN LPCTSTR pszSrc OPTIONAL, + IN size_t cbSrc, + OUT LPTSTR* ppszDestEnd OPTIONAL, + OUT size_t* pcbRemaining OPTIONAL, + IN DWORD dwFlags + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'strncpy' with + some additional parameters. In addition to functionality provided by + StringCbCopyN, this routine also returns a pointer to the end of the + destination string and the number of bytes left in the destination string + including the null terminator. The flags parameter allows additional controls. + + This routine is meant as a replacement for strncpy, but it does behave + differently. This function will not pad the destination buffer with extra + null termination characters if cbSrc is greater than the size of pszSrc. + +Arguments: + + pszDest - destination string + + cbDest - size of destination buffer in bytes. + length must be ((_tcslen(pszSrc) + 1) * sizeof(TCHAR)) to + hold all of the source including the null terminator + + pszSrc - source string + + cbSrc - maximum number of bytes to copy from source string + + ppszDestEnd - if ppszDestEnd is non-null, the function will return a + pointer to the end of the destination string. If the + function copied any data, the result will point to the + null termination character + + pcbRemaining - pcbRemaining is non-null,the function will return the + number of bytes left in the destination string, + including the null terminator + + dwFlags - controls some details of the string copy: + + STRSAFE_FILL_BEHIND_NULL + if the function succeeds, the low byte of dwFlags will be + used to fill the uninitialize part of destination buffer + behind the null terminator + + STRSAFE_IGNORE_NULLS + treat NULL string pointers like empty strings (TEXT("")). + this flag is useful for emulating functions like lstrcpy + + STRSAFE_FILL_ON_FAILURE + if the function fails, the low byte of dwFlags will be + used to fill all of the destination buffer, and it will + be null terminated. This will overwrite any truncated + string returned when the failure is + STRSAFE_E_INSUFFICIENT_BUFFER + + STRSAFE_NO_TRUNCATION / + STRSAFE_NULL_ON_FAILURE + if the function fails, the destination buffer will be set + to the empty string. This will overwrite any truncated string + returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER. + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag + is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc + may be NULL. An error may still be returned even though NULLS are ignored + due to insufficient space. + +Return Value: + + S_OK - if there was source data and it was all copied and the + resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the copy + operation failed due to insufficient space. When this + error occurs, the destination buffer is modified to + contain a truncated version of the ideal result and is + null terminated. This is useful for situations where + truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCbCopyNExA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags); +STRSAFEAPI StringCbCopyNExW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, size_t cbSrc, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags); +#ifdef UNICODE +#define StringCbCopyNEx StringCbCopyNExW +#else +#define StringCbCopyNEx StringCbCopyNExA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCbCopyNExA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags) +{ + HRESULT hr; + size_t cchDest; + size_t cchSrc; + size_t cchRemaining = 0; + + cchDest = cbDest / sizeof(char); + cchSrc = cbSrc / sizeof(char); + + if ((cchDest > STRSAFE_MAX_CCH) || + (cchSrc > STRSAFE_MAX_CCH)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCopyNExWorkerA(pszDest, cchDest, cbDest, pszSrc, cchSrc, ppszDestEnd, &cchRemaining, dwFlags); + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (pcbRemaining) + { + // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1 + *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)); + } + } + + return hr; +} + +STRSAFEAPI StringCbCopyNExW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, size_t cbSrc, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags) +{ + HRESULT hr; + size_t cchDest; + size_t cchSrc; + size_t cchRemaining = 0; + + cchDest = cbDest / sizeof(wchar_t); + cchSrc = cbSrc / sizeof(wchar_t); + + if ((cchDest > STRSAFE_MAX_CCH) || + (cchSrc > STRSAFE_MAX_CCH)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCopyNExWorkerW(pszDest, cchDest, cbDest, pszSrc, cchSrc, ppszDestEnd, &cchRemaining, dwFlags); + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (pcbRemaining) + { + // safe to multiply cchRemaining * sizeof(wchar_t) since cchRemaining < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 + *pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)); + } + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CB_FUNCTIONS + + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI +StringCchCat( + IN OUT LPTSTR pszDest, + IN size_t cchDest, + IN LPCTSTR pszSrc + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'strcat'. + The size of the destination buffer (in characters) is a parameter and this + function will not write past the end of this buffer and it will ALWAYS + null terminate the destination buffer (unless it is zero length). + + This function returns a hresult, and not a pointer. It returns + S_OK if the string was concatenated without truncation and null terminated, + otherwise it will return a failure code. In failure cases as much of pszSrc + will be appended to pszDest as possible, and pszDest will be null + terminated. + +Arguments: + + pszDest - destination string which must be null terminated + + cchDest - size of destination buffer in characters. + length must be = (_tcslen(pszDest) + _tcslen(pszSrc) + 1) + to hold all of the combine string plus the null + terminator + + pszSrc - source string which must be null terminated + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL. See StringCchCatEx if you require + the handling of NULL values. + +Return Value: + + S_OK - if there was source data and it was all concatenated and + the resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the operation + failed due to insufficient space. When this error occurs, + the destination buffer is modified to contain a truncated + version of the ideal result and is null terminated. This + is useful for situations where truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCchCatA(char* pszDest, size_t cchDest, const char* pszSrc); +STRSAFEAPI StringCchCatW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc); +#ifdef UNICODE +#define StringCchCat StringCchCatW +#else +#define StringCchCat StringCchCatA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCchCatA(char* pszDest, size_t cchDest, const char* pszSrc) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCatWorkerA(pszDest, cchDest, pszSrc); + } + + return hr; +} + +STRSAFEAPI StringCchCatW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCatWorkerW(pszDest, cchDest, pszSrc); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CCH_FUNCTIONS + + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI +StringCbCat( + IN OUT LPTSTR pszDest, + IN size_t cbDest, + IN LPCTSTR pszSrc + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'strcat'. + The size of the destination buffer (in bytes) is a parameter and this + function will not write past the end of this buffer and it will ALWAYS + null terminate the destination buffer (unless it is zero length). + + This function returns a hresult, and not a pointer. It returns + S_OK if the string was concatenated without truncation and null terminated, + otherwise it will return a failure code. In failure cases as much of pszSrc + will be appended to pszDest as possible, and pszDest will be null + terminated. + +Arguments: + + pszDest - destination string which must be null terminated + + cbDest - size of destination buffer in bytes. + length must be = ((_tcslen(pszDest) + _tcslen(pszSrc) + 1) * sizeof(TCHAR) + to hold all of the combine string plus the null + terminator + + pszSrc - source string which must be null terminated + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL. See StringCbCatEx if you require + the handling of NULL values. + +Return Value: + + S_OK - if there was source data and it was all concatenated and + the resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the operation + failed due to insufficient space. When this error occurs, + the destination buffer is modified to contain a truncated + version of the ideal result and is null terminated. This + is useful for situations where truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCbCatA(char* pszDest, size_t cbDest, const char* pszSrc); +STRSAFEAPI StringCbCatW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc); +#ifdef UNICODE +#define StringCbCat StringCbCatW +#else +#define StringCbCat StringCbCatA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCbCatA(char* pszDest, size_t cbDest, const char* 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(wchar_t* pszDest, size_t cbDest, const wchar_t* 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 // STRSAFE_INLINE +#endif // !STRSAFE_NO_CB_FUNCTIONS + + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI +StringCchCatEx( + IN OUT LPTSTR pszDest OPTIONAL, + IN size_t cchDest, + IN LPCTSTR pszSrc OPTIONAL, + OUT LPTSTR* ppszDestEnd OPTIONAL, + OUT size_t* pcchRemaining OPTIONAL, + IN DWORD dwFlags + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'strcat' with + some additional parameters. In addition to functionality provided by + StringCchCat, this routine also returns a pointer to the end of the + destination string and the number of characters left in the destination string + including the null terminator. The flags parameter allows additional controls. + +Arguments: + + pszDest - destination string which must be null terminated + + cchDest - size of destination buffer in characters + length must be (_tcslen(pszDest) + _tcslen(pszSrc) + 1) + to hold all of the combine string plus the null + terminator. + + pszSrc - source string which must be null terminated + + ppszDestEnd - if ppszDestEnd is non-null, the function will return a + pointer to the end of the destination string. If the + function appended any data, the result will point to the + null termination character + + pcchRemaining - if pcchRemaining is non-null, the function will return the + number of characters left in the destination string, + including the null terminator + + dwFlags - controls some details of the string copy: + + STRSAFE_FILL_BEHIND_NULL + if the function succeeds, the low byte of dwFlags will be + used to fill the uninitialize part of destination buffer + behind the null terminator + + STRSAFE_IGNORE_NULLS + treat NULL string pointers like empty strings (TEXT("")). + this flag is useful for emulating functions like lstrcat + + STRSAFE_FILL_ON_FAILURE + if the function fails, the low byte of dwFlags will be + used to fill all of the destination buffer, and it will + be null terminated. This will overwrite any pre-existing + or truncated string + + STRSAFE_NULL_ON_FAILURE + if the function fails, the destination buffer will be set + to the empty string. This will overwrite any pre-existing or + truncated string + + STRSAFE_NO_TRUNCATION + if the function returns STRSAFE_E_INSUFFICIENT_BUFFER, pszDest + will not contain a truncated string, it will remain unchanged. + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag + is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc + may be NULL. An error may still be returned even though NULLS are ignored + due to insufficient space. + +Return Value: + + S_OK - if there was source data and it was all concatenated and + the resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the operation + failed due to insufficient space. When this error + occurs, the destination buffer is modified to contain + a truncated version of the ideal result and is null + terminated. This is useful for situations where + truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCchCatExA(char* pszDest, size_t cchDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFEAPI StringCchCatExW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +#ifdef UNICODE +#define StringCchCatEx StringCchCatExW +#else +#define StringCchCatEx StringCchCatExA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCchCatExA(char* pszDest, size_t cchDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + + // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1 + cbDest = cchDest * sizeof(char); + + hr = StringCatExWorkerA(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, pcchRemaining, dwFlags); + } + + return hr; +} + +STRSAFEAPI StringCchCatExW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + + // safe to multiply cchDest * sizeof(wchar_t) since cchDest < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 + cbDest = cchDest * sizeof(wchar_t); + + hr = StringCatExWorkerW(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, pcchRemaining, dwFlags); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CCH_FUNCTIONS + + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI +StringCbCatEx( + IN OUT LPTSTR pszDest OPTIONAL, + IN size_t cbDest, + IN LPCTSTR pszSrc OPTIONAL, + OUT LPTSTR* ppszDestEnd OPTIONAL, + OUT size_t* pcbRemaining OPTIONAL, + IN DWORD dwFlags + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'strcat' with + some additional parameters. In addition to functionality provided by + StringCbCat, this routine also returns a pointer to the end of the + destination string and the number of bytes left in the destination string + including the null terminator. The flags parameter allows additional controls. + +Arguments: + + pszDest - destination string which must be null terminated + + cbDest - size of destination buffer in bytes. + length must be ((_tcslen(pszDest) + _tcslen(pszSrc) + 1) * sizeof(TCHAR) + to hold all of the combine string plus the null + terminator. + + pszSrc - source string which must be null terminated + + ppszDestEnd - if ppszDestEnd is non-null, the function will return a + pointer to the end of the destination string. If the + function appended any data, the result will point to the + null termination character + + pcbRemaining - if pcbRemaining is non-null, the function will return + the number of bytes left in the destination string, + including the null terminator + + dwFlags - controls some details of the string copy: + + STRSAFE_FILL_BEHIND_NULL + if the function succeeds, the low byte of dwFlags will be + used to fill the uninitialize part of destination buffer + behind the null terminator + + STRSAFE_IGNORE_NULLS + treat NULL string pointers like empty strings (TEXT("")). + this flag is useful for emulating functions like lstrcat + + STRSAFE_FILL_ON_FAILURE + if the function fails, the low byte of dwFlags will be + used to fill all of the destination buffer, and it will + be null terminated. This will overwrite any pre-existing + or truncated string + + STRSAFE_NULL_ON_FAILURE + if the function fails, the destination buffer will be set + to the empty string. This will overwrite any pre-existing or + truncated string + + STRSAFE_NO_TRUNCATION + if the function returns STRSAFE_E_INSUFFICIENT_BUFFER, pszDest + will not contain a truncated string, it will remain unchanged. + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag + is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc + may be NULL. An error may still be returned even though NULLS are ignored + due to insufficient space. + +Return Value: + + S_OK - if there was source data and it was all concatenated + and the resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the operation + failed due to insufficient space. When this error + occurs, the destination buffer is modified to contain + a truncated version of the ideal result and is null + terminated. This is useful for situations where + truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCbCatExA(char* pszDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags); +STRSAFEAPI StringCbCatExW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags); +#ifdef UNICODE +#define StringCbCatEx StringCbCatExW +#else +#define StringCbCatEx StringCbCatExA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCbCatExA(char* pszDest, size_t cbDest, const char* pszSrc, char** 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) + { + // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1 + *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)); + } + } + + return hr; +} + +STRSAFEAPI StringCbCatExW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, wchar_t** 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) + { + // safe to multiply cchRemaining * sizeof(wchar_t) since cchRemaining < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 + *pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)); + } + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CB_FUNCTIONS + + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI +StringCchCatN( + IN OUT LPTSTR pszDest, + IN size_t cchDest, + IN LPCTSTR pszSrc, + IN size_t cchMaxAppend + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'strncat'. + The size of the destination buffer (in characters) is a parameter as well as + the maximum number of characters to append, excluding the null terminator. + This function will not write past the end of the destination buffer and it will + ALWAYS null terminate pszDest (unless it is zero length). + + This function returns a hresult, and not a pointer. It returns + S_OK if all of pszSrc or the first cchMaxAppend characters were appended + to the destination string and it was null terminated, otherwise it will + return a failure code. In failure cases as much of pszSrc will be appended + to pszDest as possible, and pszDest will be null terminated. + +Arguments: + + pszDest - destination string which must be null terminated + + cchDest - size of destination buffer in characters. + length must be (_tcslen(pszDest) + min(cchMaxAppend, _tcslen(pszSrc)) + 1) + to hold all of the combine string plus the null + terminator. + + pszSrc - source string + + cchMaxAppend - maximum number of characters to append + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL. See StringCchCatNEx if you require + the handling of NULL values. + +Return Value: + + S_OK - if all of pszSrc or the first cchMaxAppend characters + were concatenated to pszDest and the resultant dest + string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the operation + failed due to insufficient space. When this error + occurs, the destination buffer is modified to contain + a truncated version of the ideal result and is null + terminated. This is useful for situations where + truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCchCatNA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend); +STRSAFEAPI StringCchCatNW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchMaxAppend); +#ifdef UNICODE +#define StringCchCatN StringCchCatNW +#else +#define StringCchCatN StringCchCatNA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCchCatNA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCatNWorkerA(pszDest, cchDest, pszSrc, cchMaxAppend); + } + + return hr; +} + +STRSAFEAPI StringCchCatNW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchMaxAppend) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCatNWorkerW(pszDest, cchDest, pszSrc, cchMaxAppend); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CCH_FUNCTIONS + + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI +StringCbCatN( + IN OUT LPTSTR pszDest, + IN size_t cbDest, + IN LPCTSTR pszSrc, + IN size_t cbMaxAppend + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'strncat'. + The size of the destination buffer (in bytes) is a parameter as well as + the maximum number of bytes to append, excluding the null terminator. + This function will not write past the end of the destination buffer and it will + ALWAYS null terminate pszDest (unless it is zero length). + + This function returns a hresult, and not a pointer. It returns + S_OK if all of pszSrc or the first cbMaxAppend bytes were appended + to the destination string and it was null terminated, otherwise it will + return a failure code. In failure cases as much of pszSrc will be appended + to pszDest as possible, and pszDest will be null terminated. + +Arguments: + + pszDest - destination string which must be null terminated + + cbDest - size of destination buffer in bytes. + length must be ((_tcslen(pszDest) + min(cbMaxAppend / sizeof(TCHAR), _tcslen(pszSrc)) + 1) * sizeof(TCHAR) + to hold all of the combine string plus the null + terminator. + + pszSrc - source string + + cbMaxAppend - maximum number of bytes to append + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL. See StringCbCatNEx if you require + the handling of NULL values. + +Return Value: + + S_OK - if all of pszSrc or the first cbMaxAppend bytes were + concatenated to pszDest and the resultant dest string + was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the operation + failed due to insufficient space. When this error + occurs, the destination buffer is modified to contain + a truncated version of the ideal result and is null + terminated. This is useful for situations where + truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCbCatNA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbMaxAppend); +STRSAFEAPI StringCbCatNW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, size_t cbMaxAppend); +#ifdef UNICODE +#define StringCbCatN StringCbCatNW +#else +#define StringCbCatN StringCbCatNA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCbCatNA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbMaxAppend) +{ + HRESULT hr; + size_t cchDest; + + cchDest = cbDest / sizeof(char); + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cchMaxAppend; + + cchMaxAppend = cbMaxAppend / sizeof(char); + + hr = StringCatNWorkerA(pszDest, cchDest, pszSrc, cchMaxAppend); + } + + return hr; +} + +STRSAFEAPI StringCbCatNW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, size_t cbMaxAppend) +{ + HRESULT hr; + size_t cchDest; + + cchDest = cbDest / sizeof(wchar_t); + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cchMaxAppend; + + cchMaxAppend = cbMaxAppend / sizeof(wchar_t); + + hr = StringCatNWorkerW(pszDest, cchDest, pszSrc, cchMaxAppend); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CB_FUNCTIONS + + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI +StringCchCatNEx( + IN OUT LPTSTR pszDest OPTIONAL, + IN size_t cchDest, + IN LPCTSTR pszSrc OPTIONAL, + IN size_t cchMaxAppend, + OUT LPTSTR* ppszDestEnd OPTIONAL, + OUT size_t* pcchRemaining OPTIONAL, + IN DWORD dwFlags + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'strncat', with + some additional parameters. In addition to functionality provided by + StringCchCatN, this routine also returns a pointer to the end of the + destination string and the number of characters left in the destination string + including the null terminator. The flags parameter allows additional controls. + +Arguments: + + pszDest - destination string which must be null terminated + + cchDest - size of destination buffer in characters. + length must be (_tcslen(pszDest) + min(cchMaxAppend, _tcslen(pszSrc)) + 1) + to hold all of the combine string plus the null + terminator. + + pszSrc - source string + + cchMaxAppend - maximum number of characters to append + + ppszDestEnd - if ppszDestEnd is non-null, the function will return a + pointer to the end of the destination string. If the + function appended any data, the result will point to the + null termination character + + pcchRemaining - if pcchRemaining is non-null, the function will return the + number of characters left in the destination string, + including the null terminator + + dwFlags - controls some details of the string copy: + + STRSAFE_FILL_BEHIND_NULL + if the function succeeds, the low byte of dwFlags will be + used to fill the uninitialize part of destination buffer + behind the null terminator + + STRSAFE_IGNORE_NULLS + treat NULL string pointers like empty strings (TEXT("")) + + STRSAFE_FILL_ON_FAILURE + if the function fails, the low byte of dwFlags will be + used to fill all of the destination buffer, and it will + be null terminated. This will overwrite any pre-existing + or truncated string + + STRSAFE_NULL_ON_FAILURE + if the function fails, the destination buffer will be set + to the empty string. This will overwrite any pre-existing or + truncated string + + STRSAFE_NO_TRUNCATION + if the function returns STRSAFE_E_INSUFFICIENT_BUFFER, pszDest + will not contain a truncated string, it will remain unchanged. + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag + is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc + may be NULL. An error may still be returned even though NULLS are ignored + due to insufficient space. + +Return Value: + + S_OK - if all of pszSrc or the first cchMaxAppend characters + were concatenated to pszDest and the resultant dest + string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the operation + failed due to insufficient space. When this error + occurs, the destination buffer is modified to contain + a truncated version of the ideal result and is null + terminated. This is useful for situations where + truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCchCatNExA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFEAPI StringCchCatNExW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchMaxAppend, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +#ifdef UNICODE +#define StringCchCatNEx StringCchCatNExW +#else +#define StringCchCatNEx StringCchCatNExA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCchCatNExA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + + // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1 + cbDest = cchDest * sizeof(char); + + hr = StringCatNExWorkerA(pszDest, cchDest, cbDest, pszSrc, cchMaxAppend, ppszDestEnd, pcchRemaining, dwFlags); + } + + return hr; +} + +STRSAFEAPI StringCchCatNExW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchMaxAppend, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + + // safe to multiply cchDest * sizeof(wchar_t) since cchDest < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 + cbDest = cchDest * sizeof(wchar_t); + + hr = StringCatNExWorkerW(pszDest, cchDest, cbDest, pszSrc, cchMaxAppend, ppszDestEnd, pcchRemaining, dwFlags); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CCH_FUNCTIONS + + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI +StringCbCatNEx( + IN OUT LPTSTR pszDest OPTIONAL, + IN size_t cbDest, + IN LPCTSTR pszSrc OPTIONAL, + IN size_t cbMaxAppend, + OUT LPTSTR* ppszDestEnd OPTIONAL, + OUT size_t* pcchRemaining OPTIONAL, + IN DWORD dwFlags + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'strncat', with + some additional parameters. In addition to functionality provided by + StringCbCatN, this routine also returns a pointer to the end of the + destination string and the number of bytes left in the destination string + including the null terminator. The flags parameter allows additional controls. + +Arguments: + + pszDest - destination string which must be null terminated + + cbDest - size of destination buffer in bytes. + length must be ((_tcslen(pszDest) + min(cbMaxAppend / sizeof(TCHAR), _tcslen(pszSrc)) + 1) * sizeof(TCHAR) + to hold all of the combine string plus the null + terminator. + + pszSrc - source string + + cbMaxAppend - maximum number of bytes to append + + ppszDestEnd - if ppszDestEnd is non-null, the function will return a + pointer to the end of the destination string. If the + function appended any data, the result will point to the + null termination character + + pcbRemaining - if pcbRemaining is non-null, the function will return the + number of bytes left in the destination string, + including the null terminator + + dwFlags - controls some details of the string copy: + + STRSAFE_FILL_BEHIND_NULL + if the function succeeds, the low byte of dwFlags will be + used to fill the uninitialize part of destination buffer + behind the null terminator + + STRSAFE_IGNORE_NULLS + treat NULL string pointers like empty strings (TEXT("")) + + STRSAFE_FILL_ON_FAILURE + if the function fails, the low byte of dwFlags will be + used to fill all of the destination buffer, and it will + be null terminated. This will overwrite any pre-existing + or truncated string + + STRSAFE_NULL_ON_FAILURE + if the function fails, the destination buffer will be set + to the empty string. This will overwrite any pre-existing or + truncated string + + STRSAFE_NO_TRUNCATION + if the function returns STRSAFE_E_INSUFFICIENT_BUFFER, pszDest + will not contain a truncated string, it will remain unchanged. + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag + is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc + may be NULL. An error may still be returned even though NULLS are ignored + due to insufficient space. + +Return Value: + + S_OK - if all of pszSrc or the first cbMaxAppend bytes were + concatenated to pszDest and the resultant dest string + was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the operation + failed due to insufficient space. When this error + occurs, the destination buffer is modified to contain + a truncated version of the ideal result and is null + terminated. This is useful for situations where + truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCbCatNExA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbMaxAppend, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags); +STRSAFEAPI StringCbCatNExW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, size_t cbMaxAppend, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags); +#ifdef UNICODE +#define StringCbCatNEx StringCbCatNExW +#else +#define StringCbCatNEx StringCbCatNExA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCbCatNExA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbMaxAppend, char** 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 + { + size_t cchMaxAppend; + + cchMaxAppend = cbMaxAppend / sizeof(char); + + hr = StringCatNExWorkerA(pszDest, cchDest, cbDest, pszSrc, cchMaxAppend, ppszDestEnd, &cchRemaining, dwFlags); + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (pcbRemaining) + { + // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1 + *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)); + } + } + + return hr; +} + +STRSAFEAPI StringCbCatNExW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, size_t cbMaxAppend, wchar_t** 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 + { + size_t cchMaxAppend; + + cchMaxAppend = cbMaxAppend / sizeof(wchar_t); + + hr = StringCatNExWorkerW(pszDest, cchDest, cbDest, pszSrc, cchMaxAppend, ppszDestEnd, &cchRemaining, dwFlags); + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (pcbRemaining) + { + // safe to multiply cchRemaining * sizeof(wchar_t) since cchRemaining < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 + *pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)); + } + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CB_FUNCTIONS + + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI +StringCchVPrintf( + OUT LPTSTR pszDest, + IN size_t cchDest, + IN LPCTSTR pszFormat, + IN va_list argList + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'vsprintf'. + The size of the destination buffer (in characters) is a parameter and + this function will not write past the end of this buffer and it will + ALWAYS null terminate the destination buffer (unless it is zero length). + + This function returns a hresult, and not a pointer. It returns + S_OK if the string was printed without truncation and null terminated, + otherwise it will return a failure code. In failure cases it will return + a truncated version of the ideal result. + +Arguments: + + pszDest - destination string + + cchDest - size of destination buffer in characters + length must be sufficient to hold the resulting formatted + string, including the null terminator. + + pszFormat - format string which must be null terminated + + argList - va_list from the variable arguments according to the + stdarg.h convention + +Notes: + Behavior is undefined if destination, format strings or any arguments + strings overlap. + + pszDest and pszFormat should not be NULL. See StringCchVPrintfEx if you + require the handling of NULL values. + +Return Value: + + S_OK - if there was sufficient space in the dest buffer for + the resultant string and it was null terminated. + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the print + operation failed due to insufficient space. When this + error occurs, the destination buffer is modified to + contain a truncated version of the ideal result and is + null terminated. This is useful for situations where + truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCchVPrintfA(char* pszDest, size_t cchDest, const char* pszFormat, va_list argList); +STRSAFEAPI StringCchVPrintfW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszFormat, va_list argList); +#ifdef UNICODE +#define StringCchVPrintf StringCchVPrintfW +#else +#define StringCchVPrintf StringCchVPrintfA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCchVPrintfA(char* pszDest, size_t cchDest, const char* 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(wchar_t* pszDest, size_t cchDest, const wchar_t* 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 // STRSAFE_INLINE +#endif // !STRSAFE_NO_CCH_FUNCTIONS + + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI +StringCbVPrintf( + OUT LPTSTR pszDest, + IN size_t cbDest, + IN LPCTSTR pszFormat, + IN va_list argList + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'vsprintf'. + The size of the destination buffer (in bytes) is a parameter and + this function will not write past the end of this buffer and it will + ALWAYS null terminate the destination buffer (unless it is zero length). + + This function returns a hresult, and not a pointer. It returns + S_OK if the string was printed without truncation and null terminated, + otherwise it will return a failure code. In failure cases it will return + a truncated version of the ideal result. + +Arguments: + + pszDest - destination string + + cbDest - size of destination buffer in bytes + length must be sufficient to hold the resulting formatted + string, including the null terminator. + + pszFormat - format string which must be null terminated + + argList - va_list from the variable arguments according to the + stdarg.h convention + +Notes: + Behavior is undefined if destination, format strings or any arguments + strings overlap. + + pszDest and pszFormat should not be NULL. See StringCbVPrintfEx if you + require the handling of NULL values. + + +Return Value: + + S_OK - if there was sufficient space in the dest buffer for + the resultant string and it was null terminated. + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the print + operation failed due to insufficient space. When this + error occurs, the destination buffer is modified to + contain a truncated version of the ideal result and is + null terminated. This is useful for situations where + truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCbVPrintfA(char* pszDest, size_t cbDest, const char* pszFormat, va_list argList); +STRSAFEAPI StringCbVPrintfW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszFormat, va_list argList); +#ifdef UNICODE +#define StringCbVPrintf StringCbVPrintfW +#else +#define StringCbVPrintf StringCbVPrintfA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCbVPrintfA(char* pszDest, size_t cbDest, const char* 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(wchar_t* pszDest, size_t cbDest, const wchar_t* 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 // STRSAFE_INLINE +#endif // !STRSAFE_NO_CB_FUNCTIONS + + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI +StringCchPrintf( + OUT LPTSTR pszDest, + IN size_t cchDest, + IN LPCTSTR pszFormat, + ... + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'sprintf'. + The size of the destination buffer (in characters) is a parameter and + this function will not write past the end of this buffer and it will + ALWAYS null terminate the destination buffer (unless it is zero length). + + This function returns a hresult, and not a pointer. It returns + S_OK if the string was printed without truncation and null terminated, + otherwise it will return a failure code. In failure cases it will return + a truncated version of the ideal result. + +Arguments: + + pszDest - destination string + + cchDest - size of destination buffer in characters + length must be sufficient to hold the resulting formatted + string, including the null terminator. + + pszFormat - format string which must be null terminated + + ... - additional parameters to be formatted according to + the format string + +Notes: + Behavior is undefined if destination, format strings or any arguments + strings overlap. + + pszDest and pszFormat should not be NULL. See StringCchPrintfEx if you + require the handling of NULL values. + +Return Value: + + S_OK - if there was sufficient space in the dest buffer for + the resultant string and it was null terminated. + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the print + operation failed due to insufficient space. When this + error occurs, the destination buffer is modified to + contain a truncated version of the ideal result and is + null terminated. This is useful for situations where + truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCchPrintfA(char* pszDest, size_t cchDest, const char* pszFormat, ...); +STRSAFEAPI StringCchPrintfW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszFormat, ...); +#ifdef UNICODE +#define StringCchPrintf StringCchPrintfW +#else +#define StringCchPrintf StringCchPrintfA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCchPrintfA(char* pszDest, size_t cchDest, const char* 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(wchar_t* pszDest, size_t cchDest, const wchar_t* 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 // STRSAFE_INLINE +#endif // !STRSAFE_NO_CCH_FUNCTIONS + + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI +StringCbPrintf( + OUT LPTSTR pszDest, + IN size_t cbDest, + IN LPCTSTR pszFormat, + ... + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'sprintf'. + The size of the destination buffer (in bytes) is a parameter and + this function will not write past the end of this buffer and it will + ALWAYS null terminate the destination buffer (unless it is zero length). + + This function returns a hresult, and not a pointer. It returns + S_OK if the string was printed without truncation and null terminated, + otherwise it will return a failure code. In failure cases it will return + a truncated version of the ideal result. + +Arguments: + + pszDest - destination string + + cbDest - size of destination buffer in bytes + length must be sufficient to hold the resulting formatted + string, including the null terminator. + + pszFormat - format string which must be null terminated + + ... - additional parameters to be formatted according to + the format string + +Notes: + Behavior is undefined if destination, format strings or any arguments + strings overlap. + + pszDest and pszFormat should not be NULL. See StringCbPrintfEx if you + require the handling of NULL values. + + +Return Value: + + S_OK - if there was sufficient space in the dest buffer for + the resultant string and it was null terminated. + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the print + operation failed due to insufficient space. When this + error occurs, the destination buffer is modified to + contain a truncated version of the ideal result and is + null terminated. This is useful for situations where + truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCbPrintfA(char* pszDest, size_t cbDest, const char* pszFormat, ...); +STRSAFEAPI StringCbPrintfW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszFormat, ...); +#ifdef UNICODE +#define StringCbPrintf StringCbPrintfW +#else +#define StringCbPrintf StringCbPrintfA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCbPrintfA(char* pszDest, size_t cbDest, const char* 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(wchar_t* pszDest, size_t cbDest, const wchar_t* 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 // STRSAFE_INLINE +#endif // !STRSAFE_NO_CB_FUNCTIONS + + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI +StringCchPrintfEx( + OUT LPTSTR pszDest OPTIONAL, + IN size_t cchDest, + OUT LPTSTR* ppszDestEnd OPTIONAL, + OUT size_t* pcchRemaining OPTIONAL, + IN DWORD dwFlags, + IN LPCTSTR pszFormat OPTIONAL, + ... + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'sprintf' with + some additional parameters. In addition to functionality provided by + StringCchPrintf, this routine also returns a pointer to the end of the + destination string and the number of characters left in the destination string + including the null terminator. The flags parameter allows additional controls. + +Arguments: + + pszDest - destination string + + cchDest - size of destination buffer in characters. + length must be sufficient to contain the resulting + formatted string plus the null terminator. + + ppszDestEnd - if ppszDestEnd is non-null, the function will return a + pointer to the end of the destination string. If the + function printed any data, the result will point to the + null termination character + + pcchRemaining - if pcchRemaining is non-null, the function will return + the number of characters left in the destination string, + including the null terminator + + dwFlags - controls some details of the string copy: + + STRSAFE_FILL_BEHIND_NULL + if the function succeeds, the low byte of dwFlags will be + used to fill the uninitialize part of destination buffer + behind the null terminator + + STRSAFE_IGNORE_NULLS + treat NULL string pointers like empty strings (TEXT("")) + + STRSAFE_FILL_ON_FAILURE + if the function fails, the low byte of dwFlags will be + used to fill all of the destination buffer, and it will + be null terminated. This will overwrite any truncated + string returned when the failure is + STRSAFE_E_INSUFFICIENT_BUFFER + + STRSAFE_NO_TRUNCATION / + STRSAFE_NULL_ON_FAILURE + if the function fails, the destination buffer will be set + to the empty string. This will overwrite any truncated string + returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER. + + pszFormat - format string which must be null terminated + + ... - additional parameters to be formatted according to + the format string + +Notes: + Behavior is undefined if destination, format strings or any arguments + strings overlap. + + pszDest and pszFormat should not be NULL unless the STRSAFE_IGNORE_NULLS + flag is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and + pszFormat may be NULL. An error may still be returned even though NULLS + are ignored due to insufficient space. + +Return Value: + + S_OK - if there was source data and it was all concatenated and + the resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the print + operation failed due to insufficient space. When this + error occurs, the destination buffer is modified to + contain a truncated version of the ideal result and is + null terminated. This is useful for situations where + truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCchPrintfExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, ...); +STRSAFEAPI StringCchPrintfExW(wchar_t* pszDest, size_t cchDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const wchar_t* pszFormat, ...); +#ifdef UNICODE +#define StringCchPrintfEx StringCchPrintfExW +#else +#define StringCchPrintfEx StringCchPrintfExA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCchPrintfExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, ...) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + va_list argList; + + // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1 + 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(wchar_t* pszDest, size_t cchDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const wchar_t* pszFormat, ...) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + va_list argList; + + // safe to multiply cchDest * sizeof(wchar_t) since cchDest < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 + 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 // STRSAFE_INLINE +#endif // !STRSAFE_NO_CCH_FUNCTIONS + + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI +StringCbPrintfEx( + OUT LPTSTR pszDest OPTIONAL, + IN size_t cbDest, + OUT LPTSTR* ppszDestEnd OPTIONAL, + OUT size_t* pcbRemaining OPTIONAL, + IN DWORD dwFlags, + IN LPCTSTR pszFormat OPTIONAL, + ... + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'sprintf' with + some additional parameters. In addition to functionality provided by + StringCbPrintf, this routine also returns a pointer to the end of the + destination string and the number of bytes left in the destination string + including the null terminator. The flags parameter allows additional controls. + +Arguments: + + pszDest - destination string + + cbDest - size of destination buffer in bytes. + length must be sufficient to contain the resulting + formatted string plus the null terminator. + + ppszDestEnd - if ppszDestEnd is non-null, the function will return a + pointer to the end of the destination string. If the + function printed any data, the result will point to the + null termination character + + pcbRemaining - if pcbRemaining is non-null, the function will return + the number of bytes left in the destination string, + including the null terminator + + dwFlags - controls some details of the string copy: + + STRSAFE_FILL_BEHIND_NULL + if the function succeeds, the low byte of dwFlags will be + used to fill the uninitialize part of destination buffer + behind the null terminator + + STRSAFE_IGNORE_NULLS + treat NULL string pointers like empty strings (TEXT("")) + + STRSAFE_FILL_ON_FAILURE + if the function fails, the low byte of dwFlags will be + used to fill all of the destination buffer, and it will + be null terminated. This will overwrite any truncated + string returned when the failure is + STRSAFE_E_INSUFFICIENT_BUFFER + + STRSAFE_NO_TRUNCATION / + STRSAFE_NULL_ON_FAILURE + if the function fails, the destination buffer will be set + to the empty string. This will overwrite any truncated string + returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER. + + pszFormat - format string which must be null terminated + + ... - additional parameters to be formatted according to + the format string + +Notes: + Behavior is undefined if destination, format strings or any arguments + strings overlap. + + pszDest and pszFormat should not be NULL unless the STRSAFE_IGNORE_NULLS + flag is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and + pszFormat may be NULL. An error may still be returned even though NULLS + are ignored due to insufficient space. + +Return Value: + + S_OK - if there was source data and it was all concatenated and + the resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the print + operation failed due to insufficient space. When this + error occurs, the destination buffer is modified to + contain a truncated version of the ideal result and is + null terminated. This is useful for situations where + truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCbPrintfExA(char* pszDest, size_t cbDest, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const char* pszFormat, ...); +STRSAFEAPI StringCbPrintfExW(wchar_t* pszDest, size_t cbDest, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const wchar_t* pszFormat, ...); +#ifdef UNICODE +#define StringCbPrintfEx StringCbPrintfExW +#else +#define StringCbPrintfEx StringCbPrintfExA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCbPrintfExA(char* pszDest, size_t cbDest, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const char* 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) + { + // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1 + *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)); + } + } + + return hr; +} + +STRSAFEAPI StringCbPrintfExW(wchar_t* pszDest, size_t cbDest, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const wchar_t* 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) + { + // safe to multiply cchRemaining * sizeof(wchar_t) since cchRemaining < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 + *pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)); + } + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CB_FUNCTIONS + + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI +StringCchVPrintfEx( + OUT LPTSTR pszDest OPTIONAL, + IN size_t cchDest, + OUT LPTSTR* ppszDestEnd OPTIONAL, + OUT size_t* pcchRemaining OPTIONAL, + IN DWORD dwFlags, + IN LPCTSTR pszFormat OPTIONAL, + IN va_list argList + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'vsprintf' with + some additional parameters. In addition to functionality provided by + StringCchVPrintf, this routine also returns a pointer to the end of the + destination string and the number of characters left in the destination string + including the null terminator. The flags parameter allows additional controls. + +Arguments: + + pszDest - destination string + + cchDest - size of destination buffer in characters. + length must be sufficient to contain the resulting + formatted string plus the null terminator. + + ppszDestEnd - if ppszDestEnd is non-null, the function will return a + pointer to the end of the destination string. If the + function printed any data, the result will point to the + null termination character + + pcchRemaining - if pcchRemaining is non-null, the function will return + the number of characters left in the destination string, + including the null terminator + + dwFlags - controls some details of the string copy: + + STRSAFE_FILL_BEHIND_NULL + if the function succeeds, the low byte of dwFlags will be + used to fill the uninitialize part of destination buffer + behind the null terminator + + STRSAFE_IGNORE_NULLS + treat NULL string pointers like empty strings (TEXT("")) + + STRSAFE_FILL_ON_FAILURE + if the function fails, the low byte of dwFlags will be + used to fill all of the destination buffer, and it will + be null terminated. This will overwrite any truncated + string returned when the failure is + STRSAFE_E_INSUFFICIENT_BUFFER + + STRSAFE_NO_TRUNCATION / + STRSAFE_NULL_ON_FAILURE + if the function fails, the destination buffer will be set + to the empty string. This will overwrite any truncated string + returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER. + + pszFormat - format string which must be null terminated + + argList - va_list from the variable arguments according to the + stdarg.h convention + +Notes: + Behavior is undefined if destination, format strings or any arguments + strings overlap. + + pszDest and pszFormat should not be NULL unless the STRSAFE_IGNORE_NULLS + flag is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and + pszFormat may be NULL. An error may still be returned even though NULLS + are ignored due to insufficient space. + +Return Value: + + S_OK - if there was source data and it was all concatenated and + the resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the print + operation failed due to insufficient space. When this + error occurs, the destination buffer is modified to + contain a truncated version of the ideal result and is + null terminated. This is useful for situations where + truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCchVPrintfExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList); +STRSAFEAPI StringCchVPrintfExW(wchar_t* pszDest, size_t cchDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const wchar_t* pszFormat, va_list argList); +#ifdef UNICODE +#define StringCchVPrintfEx StringCchVPrintfExW +#else +#define StringCchVPrintfEx StringCchVPrintfExA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCchVPrintfExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + + // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1 + cbDest = cchDest * sizeof(char); + + hr = StringVPrintfExWorkerA(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags, pszFormat, argList); + } + + return hr; +} + +STRSAFEAPI StringCchVPrintfExW(wchar_t* pszDest, size_t cchDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const wchar_t* pszFormat, va_list argList) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + + // safe to multiply cchDest * sizeof(wchar_t) since cchDest < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 + cbDest = cchDest * sizeof(wchar_t); + + hr = StringVPrintfExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags, pszFormat, argList); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CCH_FUNCTIONS + + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI +StringCbVPrintfEx( + OUT LPTSTR pszDest OPTIONAL, + IN size_t cbDest, + OUT LPTSTR* ppszDestEnd OPTIONAL, + OUT size_t* pcbRemaining OPTIONAL, + IN DWORD dwFlags, + IN LPCTSTR pszFormat OPTIONAL, + IN va_list argList + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'vsprintf' with + some additional parameters. In addition to functionality provided by + StringCbVPrintf, this routine also returns a pointer to the end of the + destination string and the number of characters left in the destination string + including the null terminator. The flags parameter allows additional controls. + +Arguments: + + pszDest - destination string + + cbDest - size of destination buffer in bytes. + length must be sufficient to contain the resulting + formatted string plus the null terminator. + + ppszDestEnd - if ppszDestEnd is non-null, the function will return + a pointer to the end of the destination string. If the + function printed any data, the result will point to the + null termination character + + pcbRemaining - if pcbRemaining is non-null, the function will return + the number of bytes left in the destination string, + including the null terminator + + dwFlags - controls some details of the string copy: + + STRSAFE_FILL_BEHIND_NULL + if the function succeeds, the low byte of dwFlags will be + used to fill the uninitialize part of destination buffer + behind the null terminator + + STRSAFE_IGNORE_NULLS + treat NULL string pointers like empty strings (TEXT("")) + + STRSAFE_FILL_ON_FAILURE + if the function fails, the low byte of dwFlags will be + used to fill all of the destination buffer, and it will + be null terminated. This will overwrite any truncated + string returned when the failure is + STRSAFE_E_INSUFFICIENT_BUFFER + + STRSAFE_NO_TRUNCATION / + STRSAFE_NULL_ON_FAILURE + if the function fails, the destination buffer will be set + to the empty string. This will overwrite any truncated string + returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER. + + pszFormat - format string which must be null terminated + + argList - va_list from the variable arguments according to the + stdarg.h convention + +Notes: + Behavior is undefined if destination, format strings or any arguments + strings overlap. + + pszDest and pszFormat should not be NULL unless the STRSAFE_IGNORE_NULLS + flag is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and + pszFormat may be NULL. An error may still be returned even though NULLS + are ignored due to insufficient space. + +Return Value: + + S_OK - if there was source data and it was all concatenated and + the resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the print + operation failed due to insufficient space. When this + error occurs, the destination buffer is modified to + contain a truncated version of the ideal result and is + null terminated. This is useful for situations where + truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCbVPrintfExA(char* pszDest, size_t cbDest, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList); +STRSAFEAPI StringCbVPrintfExW(wchar_t* pszDest, size_t cbDest, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const wchar_t* pszFormat, va_list argList); +#ifdef UNICODE +#define StringCbVPrintfEx StringCbVPrintfExW +#else +#define StringCbVPrintfEx StringCbVPrintfExA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCbVPrintfExA(char* pszDest, size_t cbDest, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const char* 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) + { + // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1 + *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)); + } + } + + return hr; +} + +STRSAFEAPI StringCbVPrintfExW(wchar_t* pszDest, size_t cbDest, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const wchar_t* 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) + { + // safe to multiply cchRemaining * sizeof(wchar_t) since cchRemaining < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 + *pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)); + } + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CB_FUNCTIONS + + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI +StringCchGets( + OUT LPTSTR pszDest, + IN size_t cchDest + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'gets'. + The size of the destination buffer (in characters) is a parameter and + this function will not write past the end of this buffer and it will + ALWAYS null terminate the destination buffer (unless it is zero length). + + This routine is not a replacement for fgets. That function does not replace + newline characters with a null terminator. + + This function returns a hresult, and not a pointer. It returns + S_OK if any characters were read from stdin and copied to pszDest and + pszDest was null terminated, otherwise it will return a failure code. + +Arguments: + + pszDest - destination string + + cchDest - size of destination buffer in characters. + +Notes: + pszDest should not be NULL. See StringCchGetsEx if you require the handling + of NULL values. + + cchDest must be > 1 for this function to succeed. + +Return Value: + + S_OK - data was read from stdin and copied, and the resultant + dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_END_OF_FILE / + HRESULT_CODE(hr) == ERROR_HANDLE_EOF + - this return value indicates an error or end-of-file + condition, use feof or ferror to determine which one has + occured. + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that there was + insufficient space in the destination buffer to copy any + data + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function. + +--*/ + +#ifndef STRSAFE_LIB_IMPL +STRSAFE_INLINE_API StringCchGetsA(char* pszDest, size_t cchDest); +STRSAFE_INLINE_API StringCchGetsW(wchar_t* pszDest, size_t cchDest); +#ifdef UNICODE +#define StringCchGets StringCchGetsW +#else +#define StringCchGets StringCchGetsA +#endif // !UNICODE + +STRSAFE_INLINE_API StringCchGetsA(char* pszDest, size_t cchDest) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + + // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1 + cbDest = cchDest * sizeof(char); + + hr = StringGetsExWorkerA(pszDest, cchDest, cbDest, NULL, NULL, 0); + } + + return hr; +} + +STRSAFE_INLINE_API StringCchGetsW(wchar_t* pszDest, size_t cchDest) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + + // safe to multiply cchDest * sizeof(wchar_t) since cchDest < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 + cbDest = cchDest * sizeof(wchar_t); + + hr = StringGetsExWorkerW(pszDest, cchDest, cbDest, NULL, NULL, 0); + } + + return hr; +} +#endif // !STRSAFE_NO_CCH_FUNCTIONS +#endif // !STRSAFE_LIB_IMPL + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI +StringCbGets( + OUT LPTSTR pszDest, + IN size_t cbDest + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'gets'. + The size of the destination buffer (in bytes) is a parameter and + this function will not write past the end of this buffer and it will + ALWAYS null terminate the destination buffer (unless it is zero length). + + This routine is not a replacement for fgets. That function does not replace + newline characters with a null terminator. + + This function returns a hresult, and not a pointer. It returns + S_OK if any characters were read from stdin and copied to pszDest + and pszDest was null terminated, otherwise it will return a failure code. + +Arguments: + + pszDest - destination string + + cbDest - size of destination buffer in bytes. + +Notes: + pszDest should not be NULL. See StringCbGetsEx if you require the handling + of NULL values. + + cbDest must be > sizeof(TCHAR) for this function to succeed. + +Return Value: + + S_OK - data was read from stdin and copied, and the resultant + dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_END_OF_FILE / + HRESULT_CODE(hr) == ERROR_HANDLE_EOF + - this return value indicates an error or end-of-file + condition, use feof or ferror to determine which one has + occured. + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that there was + insufficient space in the destination buffer to copy any + data + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function. + +--*/ + +#ifndef STRSAFE_LIB_IMPL +STRSAFE_INLINE_API StringCbGetsA(char* pszDest, size_t cbDest); +STRSAFE_INLINE_API StringCbGetsW(wchar_t* pszDest, size_t cbDest); +#ifdef UNICODE +#define StringCbGets StringCbGetsW +#else +#define StringCbGets StringCbGetsA +#endif // !UNICODE + +STRSAFE_INLINE_API StringCbGetsA(char* pszDest, size_t cbDest) +{ + HRESULT hr; + size_t cchDest; + + // convert to count of characters + 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(wchar_t* pszDest, size_t cbDest) +{ + HRESULT hr; + size_t cchDest; + + // convert to count of characters + 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 // !STRSAFE_NO_CB_FUNCTIONS +#endif // !STRSAFE_LIB_IMPL + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI +StringCchGetsEx( + OUT LPTSTR pszDest OPTIONAL, + IN size_t cchDest, + OUT LPTSTR* ppszDestEnd OPTIONAL, + OUT size_t* pcchRemaining OPTIONAL, + IN DWORD dwFlags + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'gets' with + some additional parameters. In addition to functionality provided by + StringCchGets, this routine also returns a pointer to the end of the + destination string and the number of characters left in the destination string + including the null terminator. The flags parameter allows additional controls. + +Arguments: + + pszDest - destination string + + cchDest - size of destination buffer in characters. + + ppszDestEnd - if ppszDestEnd is non-null, the function will return a + pointer to the end of the destination string. If the + function copied any data, the result will point to the + null termination character + + pcchRemaining - if pcchRemaining is non-null, the function will return the + number of characters left in the destination string, + including the null terminator + + dwFlags - controls some details of the string copy: + + STRSAFE_FILL_BEHIND_NULL + if the function succeeds, the low byte of dwFlags will be + used to fill the uninitialize part of destination buffer + behind the null terminator + + STRSAFE_IGNORE_NULLS + treat NULL string pointers like empty strings (TEXT("")). + + STRSAFE_FILL_ON_FAILURE + if the function fails, the low byte of dwFlags will be + used to fill all of the destination buffer, and it will + be null terminated. + + STRSAFE_NO_TRUNCATION / + STRSAFE_NULL_ON_FAILURE + if the function fails, the destination buffer will be set + to the empty string. + +Notes: + pszDest should not be NULL unless the STRSAFE_IGNORE_NULLS flag is specified. + If STRSAFE_IGNORE_NULLS is passed and pszDest is NULL, an error may still be + returned even though NULLS are ignored + + cchDest must be > 1 for this function to succeed. + +Return Value: + + S_OK - data was read from stdin and copied, and the resultant + dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_END_OF_FILE / + HRESULT_CODE(hr) == ERROR_HANDLE_EOF + - this return value indicates an error or end-of-file + condition, use feof or ferror to determine which one has + occured. + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that there was + insufficient space in the destination buffer to copy any + data + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function. + +--*/ + +#ifndef STRSAFE_LIB_IMPL +STRSAFE_INLINE_API StringCchGetsExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFE_INLINE_API StringCchGetsExW(wchar_t* pszDest, size_t cchDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +#ifdef UNICODE +#define StringCchGetsEx StringCchGetsExW +#else +#define StringCchGetsEx StringCchGetsExA +#endif // !UNICODE + +STRSAFE_INLINE_API StringCchGetsExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + + // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1 + cbDest = cchDest * sizeof(char); + + hr = StringGetsExWorkerA(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags); + } + + return hr; +} + +STRSAFE_INLINE_API StringCchGetsExW(wchar_t* pszDest, size_t cchDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + + // safe to multiply cchDest * sizeof(wchar_t) since cchDest < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 + cbDest = cchDest * sizeof(wchar_t); + + hr = StringGetsExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags); + } + + return hr; +} +#endif // !STRSAFE_NO_CCH_FUNCTIONS +#endif // !STRSAFE_LIB_IMPL + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI +StringCbGetsEx( + OUT LPTSTR pszDest OPTIONAL, + IN size_t cbDest, + OUT LPTSTR* ppszDestEnd OPTIONAL, + OUT size_t* pcbRemaining OPTIONAL, + IN DWORD dwFlags + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'gets' with + some additional parameters. In addition to functionality provided by + StringCbGets, this routine also returns a pointer to the end of the + destination string and the number of characters left in the destination string + including the null terminator. The flags parameter allows additional controls. + +Arguments: + + pszDest - destination string + + cbDest - size of destination buffer in bytes. + + ppszDestEnd - if ppszDestEnd is non-null, the function will return a + pointer to the end of the destination string. If the + function copied any data, the result will point to the + null termination character + + pcbRemaining - if pbRemaining is non-null, the function will return the + number of bytes left in the destination string, + including the null terminator + + dwFlags - controls some details of the string copy: + + STRSAFE_FILL_BEHIND_NULL + if the function succeeds, the low byte of dwFlags will be + used to fill the uninitialize part of destination buffer + behind the null terminator + + STRSAFE_IGNORE_NULLS + treat NULL string pointers like empty strings (TEXT("")). + + STRSAFE_FILL_ON_FAILURE + if the function fails, the low byte of dwFlags will be + used to fill all of the destination buffer, and it will + be null terminated. + + STRSAFE_NO_TRUNCATION / + STRSAFE_NULL_ON_FAILURE + if the function fails, the destination buffer will be set + to the empty string. + +Notes: + pszDest should not be NULL unless the STRSAFE_IGNORE_NULLS flag is specified. + If STRSAFE_IGNORE_NULLS is passed and pszDest is NULL, an error may still be + returned even though NULLS are ignored + + cbDest must be > sizeof(TCHAR) for this function to succeed + +Return Value: + + S_OK - data was read from stdin and copied, and the resultant + dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_END_OF_FILE / + HRESULT_CODE(hr) == ERROR_HANDLE_EOF + - this return value indicates an error or end-of-file + condition, use feof or ferror to determine which one has + occured. + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that there was + insufficient space in the destination buffer to copy any + data + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function. + +--*/ + +#ifndef STRSAFE_LIB_IMPL +STRSAFE_INLINE_API StringCbGetsExA(char* pszDest, size_t cbDest, char** ppszDestEnd, size_t* pbRemaining, unsigned long dwFlags); +STRSAFE_INLINE_API StringCbGetsExW(wchar_t* pszDest, size_t cbDest, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags); +#ifdef UNICODE +#define StringCbGetsEx StringCbGetsExW +#else +#define StringCbGetsEx StringCbGetsExA +#endif // !UNICODE + +STRSAFE_INLINE_API StringCbGetsExA(char* pszDest, size_t cbDest, char** 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) + { + // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1 + *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)); + } + } + + return hr; +} + +STRSAFE_INLINE_API StringCbGetsExW(wchar_t* pszDest, size_t cbDest, wchar_t** 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) + { + // safe to multiply cchRemaining * sizeof(wchar_t) since cchRemaining < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 + *pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)); + } + } + + return hr; +} +#endif // !STRSAFE_NO_CB_FUNCTIONS +#endif // !STRSAFE_LIB_IMPL + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI +StringCchLength( + IN LPCTSTR psz, + IN size_t cchMax, + OUT size_t* pcch OPTIONAL + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'strlen'. + It is used to make sure a string is not larger than a given length, and + it optionally returns the current length in characters not including + the null terminator. + + This function returns a hresult, and not a pointer. It returns + S_OK if the string is non-null and the length including the null + terminator is less than or equal to cchMax characters. + +Arguments: + + psz - string to check the length of + + cchMax - maximum number of characters including the null terminator + that psz is allowed to contain + + pcch - if the function succeeds and pcch is non-null, the current length + in characters of psz excluding the null terminator will be returned. + This out parameter is equivalent to the return value of strlen(psz) + +Notes: + psz can be null but the function will fail + + cchMax should be greater than zero or the function will fail + +Return Value: + + S_OK - psz is non-null and the length including the null + terminator is less than or equal to cchMax characters + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function. + +--*/ + +STRSAFEAPI StringCchLengthA(const char* psz, size_t cchMax, size_t* pcch); +STRSAFEAPI StringCchLengthW(const wchar_t* psz, size_t cchMax, size_t* pcch); +#ifdef UNICODE +#define StringCchLength StringCchLengthW +#else +#define StringCchLength StringCchLengthA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCchLengthA(const char* psz, size_t cchMax, size_t* pcch) +{ + HRESULT hr; + + if ((psz == NULL) || (cchMax > STRSAFE_MAX_CCH)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringLengthWorkerA(psz, cchMax, pcch); + } + + return hr; +} + +STRSAFEAPI StringCchLengthW(const wchar_t* psz, size_t cchMax, size_t* pcch) +{ + HRESULT hr; + + if ((psz == NULL) || (cchMax > STRSAFE_MAX_CCH)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringLengthWorkerW(psz, cchMax, pcch); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CCH_FUNCTIONS + + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI +StringCbLength( + IN LPCTSTR psz, + IN size_t cbMax, + OUT size_t* pcb OPTIONAL + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'strlen'. + It is used to make sure a string is not larger than a given length, and + it optionally returns the current length in bytes not including + the null terminator. + + This function returns a hresult, and not a pointer. It returns + S_OK if the string is non-null and the length including the null + terminator is less than or equal to cbMax bytes. + +Arguments: + + psz - string to check the length of + + cbMax - maximum number of bytes including the null terminator + that psz is allowed to contain + + pcb - if the function succeeds and pcb is non-null, the current length + in bytes of psz excluding the null terminator will be returned. + This out parameter is equivalent to the return value of strlen(psz) * sizeof(TCHAR) + +Notes: + psz can be null but the function will fail + + cbMax should be greater than or equal to sizeof(TCHAR) or the function will fail + +Return Value: + + S_OK - psz is non-null and the length including the null + terminator is less than or equal to cbMax bytes + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function. + +--*/ + +STRSAFEAPI StringCbLengthA(const char* psz, size_t cchMax, size_t* pcch); +STRSAFEAPI StringCbLengthW(const wchar_t* psz, size_t cchMax, size_t* pcch); +#ifdef UNICODE +#define StringCbLength StringCbLengthW +#else +#define StringCbLength StringCbLengthA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCbLengthA(const char* psz, size_t cbMax, size_t* pcb) +{ + HRESULT hr; + size_t cchMax; + size_t cch = 0; + + cchMax = cbMax / sizeof(char); + + if ((psz == NULL) || (cchMax > STRSAFE_MAX_CCH)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringLengthWorkerA(psz, cchMax, &cch); + } + + if (SUCCEEDED(hr) && pcb) + { + // safe to multiply cch * sizeof(char) since cch < STRSAFE_MAX_CCH and sizeof(char) is 1 + *pcb = cch * sizeof(char); + } + + return hr; +} + +STRSAFEAPI StringCbLengthW(const wchar_t* psz, size_t cbMax, size_t* pcb) +{ + HRESULT hr; + size_t cchMax; + size_t cch = 0; + + cchMax = cbMax / sizeof(wchar_t); + + if ((psz == NULL) || (cchMax > STRSAFE_MAX_CCH)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringLengthWorkerW(psz, cchMax, &cch); + } + + if (SUCCEEDED(hr) && pcb) + { + // safe to multiply cch * sizeof(wchar_t) since cch < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 + *pcb = cch * sizeof(wchar_t); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CB_FUNCTIONS + + +// these are the worker functions that actually do the work +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCopyWorkerA(char* pszDest, size_t cchDest, const char* pszSrc) +{ + HRESULT hr = S_OK; + + if (cchDest == 0) + { + // can not null terminate a zero-byte dest buffer + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + while (cchDest && (*pszSrc != '\0')) + { + *pszDest++ = *pszSrc++; + cchDest--; + } + + if (cchDest == 0) + { + // we are going to truncate pszDest + pszDest--; + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + + *pszDest= '\0'; + } + + return hr; +} + +STRSAFEAPI StringCopyWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc) +{ + HRESULT hr = S_OK; + + if (cchDest == 0) + { + // can not null terminate a zero-byte dest buffer + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + while (cchDest && (*pszSrc != L'\0')) + { + *pszDest++ = *pszSrc++; + cchDest--; + } + + if (cchDest == 0) + { + // we are going to truncate pszDest + pszDest--; + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + + *pszDest= L'\0'; + } + + return hr; +} + +STRSAFEAPI StringCopyExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr = S_OK; + char* pszDestEnd = pszDest; + size_t cchRemaining = 0; + + // ASSERT(cbDest == (cchDest * sizeof(char)) || + // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char))); + + // only accept valid flags + if (dwFlags & (~STRSAFE_VALID_FLAGS)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + if (dwFlags & STRSAFE_IGNORE_NULLS) + { + if (pszDest == NULL) + { + if ((cchDest != 0) || (cbDest != 0)) + { + // NULL pszDest and non-zero cchDest/cbDest is invalid + hr = STRSAFE_E_INVALID_PARAMETER; + } + } + + if (pszSrc == NULL) + { + pszSrc = ""; + } + } + + if (SUCCEEDED(hr)) + { + if (cchDest == 0) + { + pszDestEnd = pszDest; + cchRemaining = 0; + + // only fail if there was actually src data to copy + if (*pszSrc != '\0') + { + if (pszDest == NULL) + { + 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 + { + // we are going to truncate pszDest + 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; + + // null terminate the end of the string + *pszDestEnd = '\0'; + } + } + + if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) + { + if (cchDest > 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + // null terminate the beginning of the string + *pszDestEnd = '\0'; + } + } + } + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (ppszDestEnd) + { + *ppszDestEnd = pszDestEnd; + } + + if (pcchRemaining) + { + *pcchRemaining = cchRemaining; + } + } + + return hr; +} + +STRSAFEAPI StringCopyExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr = S_OK; + wchar_t* pszDestEnd = pszDest; + size_t cchRemaining = 0; + + // ASSERT(cbDest == (cchDest * sizeof(wchar_t)) || + // cbDest == (cchDest * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t))); + + // only accept valid flags + if (dwFlags & (~STRSAFE_VALID_FLAGS)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + if (dwFlags & STRSAFE_IGNORE_NULLS) + { + if (pszDest == NULL) + { + if ((cchDest != 0) || (cbDest != 0)) + { + // NULL pszDest and non-zero cchDest/cbDest is invalid + hr = STRSAFE_E_INVALID_PARAMETER; + } + } + + if (pszSrc == NULL) + { + pszSrc = L""; + } + } + + if (SUCCEEDED(hr)) + { + if (cchDest == 0) + { + pszDestEnd = pszDest; + cchRemaining = 0; + + // only fail if there was actually src data to copy + if (*pszSrc != L'\0') + { + if (pszDest == NULL) + { + 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 + { + // we are going to truncate pszDest + 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; + + // null terminate the end of the string + *pszDestEnd = L'\0'; + } + } + + if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) + { + if (cchDest > 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + // null terminate the beginning of the string + *pszDestEnd = L'\0'; + } + } + } + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (ppszDestEnd) + { + *ppszDestEnd = pszDestEnd; + } + + if (pcchRemaining) + { + *pcchRemaining = cchRemaining; + } + } + + return hr; +} + +STRSAFEAPI StringCopyNWorkerA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc) +{ + HRESULT hr = S_OK; + + if (cchDest == 0) + { + // can not null terminate a zero-byte dest buffer + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + while (cchDest && cchSrc && (*pszSrc != '\0')) + { + *pszDest++= *pszSrc++; + cchDest--; + cchSrc--; + } + + if (cchDest == 0) + { + // we are going to truncate pszDest + pszDest--; + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + + *pszDest= '\0'; + } + + return hr; +} + +STRSAFEAPI StringCopyNWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchSrc) +{ + HRESULT hr = S_OK; + + if (cchDest == 0) + { + // can not null terminate a zero-byte dest buffer + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + while (cchDest && cchSrc && (*pszSrc != L'\0')) + { + *pszDest++= *pszSrc++; + cchDest--; + cchSrc--; + } + + if (cchDest == 0) + { + // we are going to truncate pszDest + pszDest--; + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + + *pszDest= L'\0'; + } + + return hr; +} + +STRSAFEAPI StringCopyNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, size_t cchSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr = S_OK; + char* pszDestEnd = pszDest; + size_t cchRemaining = 0; + + // ASSERT(cbDest == (cchDest * sizeof(char)) || + // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char))); + + // only accept valid flags + if (dwFlags & (~STRSAFE_VALID_FLAGS)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + if (dwFlags & STRSAFE_IGNORE_NULLS) + { + if (pszDest == NULL) + { + if ((cchDest != 0) || (cbDest != 0)) + { + // NULL pszDest and non-zero cchDest/cbDest is invalid + hr = STRSAFE_E_INVALID_PARAMETER; + } + } + + if (pszSrc == NULL) + { + pszSrc = ""; + } + } + + if (SUCCEEDED(hr)) + { + if (cchDest == 0) + { + pszDestEnd = pszDest; + cchRemaining = 0; + + // only fail if there was actually src data to copy + if (*pszSrc != '\0') + { + if (pszDest == NULL) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + } + } + else + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + while (cchRemaining && cchSrc && (*pszSrc != '\0')) + { + *pszDestEnd++= *pszSrc++; + cchRemaining--; + cchSrc--; + } + + 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 + { + // we are going to truncate pszDest + 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; + + // null terminate the end of the string + *pszDestEnd = '\0'; + } + } + + if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) + { + if (cchDest > 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + // null terminate the beginning of the string + *pszDestEnd = '\0'; + } + } + } + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (ppszDestEnd) + { + *ppszDestEnd = pszDestEnd; + } + + if (pcchRemaining) + { + *pcchRemaining = cchRemaining; + } + } + + return hr; +} + +STRSAFEAPI StringCopyNExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, const wchar_t* pszSrc, size_t cchSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr = S_OK; + wchar_t* pszDestEnd = pszDest; + size_t cchRemaining = 0; + + // ASSERT(cbDest == (cchDest * sizeof(wchar_t)) || + // cbDest == (cchDest * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t))); + + // only accept valid flags + if (dwFlags & (~STRSAFE_VALID_FLAGS)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + if (dwFlags & STRSAFE_IGNORE_NULLS) + { + if (pszDest == NULL) + { + if ((cchDest != 0) || (cbDest != 0)) + { + // NULL pszDest and non-zero cchDest/cbDest is invalid + hr = STRSAFE_E_INVALID_PARAMETER; + } + } + + if (pszSrc == NULL) + { + pszSrc = L""; + } + } + + if (SUCCEEDED(hr)) + { + if (cchDest == 0) + { + pszDestEnd = pszDest; + cchRemaining = 0; + + // only fail if there was actually src data to copy + if (*pszSrc != L'\0') + { + if (pszDest == NULL) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + } + } + else + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + while (cchRemaining && cchSrc && (*pszSrc != L'\0')) + { + *pszDestEnd++= *pszSrc++; + cchRemaining--; + cchSrc--; + } + + 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 + { + // we are going to truncate pszDest + 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; + + // null terminate the end of the string + *pszDestEnd = L'\0'; + } + } + + if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) + { + if (cchDest > 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + // null terminate the beginning of the string + *pszDestEnd = L'\0'; + } + } + } + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (ppszDestEnd) + { + *ppszDestEnd = pszDestEnd; + } + + if (pcchRemaining) + { + *pcchRemaining = cchRemaining; + } + } + + return hr; +} + +STRSAFEAPI StringCatWorkerA(char* pszDest, size_t cchDest, const char* pszSrc) +{ + HRESULT hr; + size_t cchDestCurrent; + + hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent); + + if (SUCCEEDED(hr)) + { + hr = StringCopyWorkerA(pszDest + cchDestCurrent, + cchDest - cchDestCurrent, + pszSrc); + } + + return hr; +} + +STRSAFEAPI StringCatWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc) +{ + HRESULT hr; + size_t cchDestCurrent; + + hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent); + + if (SUCCEEDED(hr)) + { + hr = StringCopyWorkerW(pszDest + cchDestCurrent, + cchDest - cchDestCurrent, + pszSrc); + } + + return hr; +} + +STRSAFEAPI StringCatExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr = S_OK; + char* pszDestEnd = pszDest; + size_t cchRemaining = 0; + + // ASSERT(cbDest == (cchDest * sizeof(char)) || + // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char))); + + // only accept valid flags + if (dwFlags & (~STRSAFE_VALID_FLAGS)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cchDestCurrent; + + if (dwFlags & STRSAFE_IGNORE_NULLS) + { + if (pszDest == NULL) + { + if ((cchDest == 0) && (cbDest == 0)) + { + cchDestCurrent = 0; + } + else + { + // NULL pszDest and non-zero cchDest/cbDest is invalid + hr = STRSAFE_E_INVALID_PARAMETER; + } + } + else + { + hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent); + + if (SUCCEEDED(hr)) + { + pszDestEnd = pszDest + cchDestCurrent; + cchRemaining = cchDest - cchDestCurrent; + } + } + + if (pszSrc == NULL) + { + pszSrc = ""; + } + } + else + { + hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent); + + if (SUCCEEDED(hr)) + { + pszDestEnd = pszDest + cchDestCurrent; + cchRemaining = cchDest - cchDestCurrent; + } + } + + if (SUCCEEDED(hr)) + { + if (cchDest == 0) + { + // only fail if there was actually src data to append + if (*pszSrc != '\0') + { + if (pszDest == NULL) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + } + } + else + { + // we handle the STRSAFE_FILL_ON_FAILURE and STRSAFE_NULL_ON_FAILURE cases below, so do not pass + // those flags through + 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) + { + // STRSAFE_NO_TRUNCATION is taken care of by StringCopyExWorkerA() + + 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; + + // null terminate the end of the string + *pszDestEnd = '\0'; + } + } + + if (dwFlags & STRSAFE_NULL_ON_FAILURE) + { + if (cchDest > 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + // null terminate the beginning of the string + *pszDestEnd = '\0'; + } + } + } + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (ppszDestEnd) + { + *ppszDestEnd = pszDestEnd; + } + + if (pcchRemaining) + { + *pcchRemaining = cchRemaining; + } + } + + return hr; +} + +STRSAFEAPI StringCatExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr = S_OK; + wchar_t* pszDestEnd = pszDest; + size_t cchRemaining = 0; + + // ASSERT(cbDest == (cchDest * sizeof(wchar_t)) || + // cbDest == (cchDest * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t))); + + // only accept valid flags + if (dwFlags & (~STRSAFE_VALID_FLAGS)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cchDestCurrent; + + if (dwFlags & STRSAFE_IGNORE_NULLS) + { + if (pszDest == NULL) + { + if ((cchDest == 0) && (cbDest == 0)) + { + cchDestCurrent = 0; + } + else + { + // NULL pszDest and non-zero cchDest/cbDest is invalid + hr = STRSAFE_E_INVALID_PARAMETER; + } + } + else + { + hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent); + + if (SUCCEEDED(hr)) + { + pszDestEnd = pszDest + cchDestCurrent; + cchRemaining = cchDest - cchDestCurrent; + } + } + + if (pszSrc == NULL) + { + pszSrc = L""; + } + } + else + { + hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent); + + if (SUCCEEDED(hr)) + { + pszDestEnd = pszDest + cchDestCurrent; + cchRemaining = cchDest - cchDestCurrent; + } + } + + if (SUCCEEDED(hr)) + { + if (cchDest == 0) + { + // only fail if there was actually src data to append + if (*pszSrc != L'\0') + { + if (pszDest == NULL) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + } + } + else + { + // we handle the STRSAFE_FILL_ON_FAILURE and STRSAFE_NULL_ON_FAILURE cases below, so do not pass + // those flags through + 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) + { + // STRSAFE_NO_TRUNCATION is taken care of by StringCopyExWorkerW() + + 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; + + // null terminate the end of the string + *pszDestEnd = L'\0'; + } + } + + if (dwFlags & STRSAFE_NULL_ON_FAILURE) + { + if (cchDest > 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + // null terminate the beginning of the string + *pszDestEnd = L'\0'; + } + } + } + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (ppszDestEnd) + { + *ppszDestEnd = pszDestEnd; + } + + if (pcchRemaining) + { + *pcchRemaining = cchRemaining; + } + } + + return hr; +} + +STRSAFEAPI StringCatNWorkerA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend) +{ + HRESULT hr; + size_t cchDestCurrent; + + hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent); + + if (SUCCEEDED(hr)) + { + hr = StringCopyNWorkerA(pszDest + cchDestCurrent, + cchDest - cchDestCurrent, + pszSrc, + cchMaxAppend); + } + + return hr; +} + +STRSAFEAPI StringCatNWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchMaxAppend) +{ + HRESULT hr; + size_t cchDestCurrent; + + hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent); + + if (SUCCEEDED(hr)) + { + hr = StringCopyNWorkerW(pszDest + cchDestCurrent, + cchDest - cchDestCurrent, + pszSrc, + cchMaxAppend); + } + + return hr; +} + +STRSAFEAPI StringCatNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, size_t cchMaxAppend, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr = S_OK; + char* pszDestEnd = pszDest; + size_t cchRemaining = 0; + size_t cchDestCurrent = 0; + + // ASSERT(cbDest == (cchDest * sizeof(char)) || + // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char))); + + // only accept valid flags + if (dwFlags & (~STRSAFE_VALID_FLAGS)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + if (dwFlags & STRSAFE_IGNORE_NULLS) + { + if (pszDest == NULL) + { + if ((cchDest == 0) && (cbDest == 0)) + { + cchDestCurrent = 0; + } + else + { + // NULL pszDest and non-zero cchDest/cbDest is invalid + hr = STRSAFE_E_INVALID_PARAMETER; + } + } + else + { + hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent); + + if (SUCCEEDED(hr)) + { + pszDestEnd = pszDest + cchDestCurrent; + cchRemaining = cchDest - cchDestCurrent; + } + } + + if (pszSrc == NULL) + { + pszSrc = ""; + } + } + else + { + hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent); + + if (SUCCEEDED(hr)) + { + pszDestEnd = pszDest + cchDestCurrent; + cchRemaining = cchDest - cchDestCurrent; + } + } + + if (SUCCEEDED(hr)) + { + if (cchDest == 0) + { + // only fail if there was actually src data to append + if (*pszSrc != '\0') + { + if (pszDest == NULL) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + } + } + else + { + // we handle the STRSAFE_FILL_ON_FAILURE and STRSAFE_NULL_ON_FAILURE cases below, so do not pass + // those flags through + hr = StringCopyNExWorkerA(pszDestEnd, + cchRemaining, + (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)), + pszSrc, + cchMaxAppend, + &pszDestEnd, + &cchRemaining, + dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE))); + } + } + } + + if (FAILED(hr)) + { + if (pszDest) + { + // STRSAFE_NO_TRUNCATION is taken care of by StringCopyNExWorkerA() + + 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; + + // null terminate the end of the string + *pszDestEnd = '\0'; + } + } + + if (dwFlags & (STRSAFE_NULL_ON_FAILURE)) + { + if (cchDest > 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + // null terminate the beginning of the string + *pszDestEnd = '\0'; + } + } + } + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (ppszDestEnd) + { + *ppszDestEnd = pszDestEnd; + } + + if (pcchRemaining) + { + *pcchRemaining = cchRemaining; + } + } + + return hr; +} + +STRSAFEAPI StringCatNExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, const wchar_t* pszSrc, size_t cchMaxAppend, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr = S_OK; + wchar_t* pszDestEnd = pszDest; + size_t cchRemaining = 0; + size_t cchDestCurrent = 0; + + + // ASSERT(cbDest == (cchDest * sizeof(wchar_t)) || + // cbDest == (cchDest * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t))); + + // only accept valid flags + if (dwFlags & (~STRSAFE_VALID_FLAGS)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + if (dwFlags & STRSAFE_IGNORE_NULLS) + { + if (pszDest == NULL) + { + if ((cchDest == 0) && (cbDest == 0)) + { + cchDestCurrent = 0; + } + else + { + // NULL pszDest and non-zero cchDest/cbDest is invalid + hr = STRSAFE_E_INVALID_PARAMETER; + } + } + else + { + hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent); + + if (SUCCEEDED(hr)) + { + pszDestEnd = pszDest + cchDestCurrent; + cchRemaining = cchDest - cchDestCurrent; + } + } + + if (pszSrc == NULL) + { + pszSrc = L""; + } + } + else + { + hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent); + + if (SUCCEEDED(hr)) + { + pszDestEnd = pszDest + cchDestCurrent; + cchRemaining = cchDest - cchDestCurrent; + } + } + + if (SUCCEEDED(hr)) + { + if (cchDest == 0) + { + // only fail if there was actually src data to append + if (*pszSrc != L'\0') + { + if (pszDest == NULL) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + } + } + else + { + // we handle the STRSAFE_FILL_ON_FAILURE and STRSAFE_NULL_ON_FAILURE cases below, so do not pass + // those flags through + hr = StringCopyNExWorkerW(pszDestEnd, + cchRemaining, + (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)), + pszSrc, + cchMaxAppend, + &pszDestEnd, + &cchRemaining, + dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE))); + } + } + } + + if (FAILED(hr)) + { + if (pszDest) + { + // STRSAFE_NO_TRUNCATION is taken care of by StringCopyNExWorkerW() + + 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; + + // null terminate the end of the string + *pszDestEnd = L'\0'; + } + } + + if (dwFlags & (STRSAFE_NULL_ON_FAILURE)) + { + if (cchDest > 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + // null terminate the beginning of the string + *pszDestEnd = L'\0'; + } + } + } + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (ppszDestEnd) + { + *ppszDestEnd = pszDestEnd; + } + + if (pcchRemaining) + { + *pcchRemaining = cchRemaining; + } + } + + return hr; +} + +STRSAFEAPI StringVPrintfWorkerA(char* pszDest, size_t cchDest, const char* pszFormat, va_list argList) +{ + HRESULT hr = S_OK; + + if (cchDest == 0) + { + // can not null terminate a zero-byte dest buffer + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + int iRet; + size_t cchMax; + + // leave the last space for the null terminator + cchMax = cchDest - 1; + + iRet = _vsnprintf(pszDest, cchMax, pszFormat, argList); + // ASSERT((iRet < 0) || (((size_t)iRet) <= cchMax)); + + if ((iRet < 0) || (((size_t)iRet) > cchMax)) + { + // need to null terminate the string + pszDest += cchMax; + *pszDest = '\0'; + + // we have truncated pszDest + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + else if (((size_t)iRet) == cchMax) + { + // need to null terminate the string + pszDest += cchMax; + *pszDest = '\0'; + } + } + + return hr; +} + +STRSAFEAPI StringVPrintfWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszFormat, va_list argList) +{ + HRESULT hr = S_OK; + + if (cchDest == 0) + { + // can not null terminate a zero-byte dest buffer + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + int iRet; + size_t cchMax; + + // leave the last space for the null terminator + cchMax = cchDest - 1; + + iRet = _vsnwprintf(pszDest, cchMax, pszFormat, argList); + // ASSERT((iRet < 0) || (((size_t)iRet) <= cchMax)); + + if ((iRet < 0) || (((size_t)iRet) > cchMax)) + { + // need to null terminate the string + pszDest += cchMax; + *pszDest = L'\0'; + + // we have truncated pszDest + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + else if (((size_t)iRet) == cchMax) + { + // need to null terminate the string + pszDest += cchMax; + *pszDest = L'\0'; + } + } + + return hr; +} + +STRSAFEAPI StringVPrintfExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList) +{ + HRESULT hr = S_OK; + char* pszDestEnd = pszDest; + size_t cchRemaining = 0; + + // ASSERT(cbDest == (cchDest * sizeof(char)) || + // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char))); + + // only accept valid flags + if (dwFlags & (~STRSAFE_VALID_FLAGS)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + if (dwFlags & STRSAFE_IGNORE_NULLS) + { + if (pszDest == NULL) + { + if ((cchDest != 0) || (cbDest != 0)) + { + // NULL pszDest and non-zero cchDest/cbDest is invalid + hr = STRSAFE_E_INVALID_PARAMETER; + } + } + + if (pszFormat == NULL) + { + pszFormat = ""; + } + } + + if (SUCCEEDED(hr)) + { + if (cchDest == 0) + { + pszDestEnd = pszDest; + cchRemaining = 0; + + // only fail if there was actually a non-empty format string + if (*pszFormat != '\0') + { + if (pszDest == NULL) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + } + } + else + { + int iRet; + size_t cchMax; + + // leave the last space for the null terminator + cchMax = cchDest - 1; + + iRet = _vsnprintf(pszDest, cchMax, pszFormat, argList); + // ASSERT((iRet < 0) || (((size_t)iRet) <= cchMax)); + + if ((iRet < 0) || (((size_t)iRet) > cchMax)) + { + // we have truncated pszDest + pszDestEnd = pszDest + cchMax; + cchRemaining = 1; + + // need to null terminate the string + *pszDestEnd = '\0'; + + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + else if (((size_t)iRet) == cchMax) + { + // string fit perfectly + pszDestEnd = pszDest + cchMax; + cchRemaining = 1; + + // need to null terminate the string + *pszDestEnd = '\0'; + } + else if (((size_t)iRet) < cchMax) + { + // there is extra room + 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; + + // null terminate the end of the string + *pszDestEnd = '\0'; + } + } + + if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) + { + if (cchDest > 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + // null terminate the beginning of the string + *pszDestEnd = '\0'; + } + } + } + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (ppszDestEnd) + { + *ppszDestEnd = pszDestEnd; + } + + if (pcchRemaining) + { + *pcchRemaining = cchRemaining; + } + } + + return hr; +} + +STRSAFEAPI StringVPrintfExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const wchar_t* pszFormat, va_list argList) +{ + HRESULT hr = S_OK; + wchar_t* pszDestEnd = pszDest; + size_t cchRemaining = 0; + + // ASSERT(cbDest == (cchDest * sizeof(wchar_t)) || + // cbDest == (cchDest * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t))); + + // only accept valid flags + if (dwFlags & (~STRSAFE_VALID_FLAGS)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + if (dwFlags & STRSAFE_IGNORE_NULLS) + { + if (pszDest == NULL) + { + if ((cchDest != 0) || (cbDest != 0)) + { + // NULL pszDest and non-zero cchDest/cbDest is invalid + hr = STRSAFE_E_INVALID_PARAMETER; + } + } + + if (pszFormat == NULL) + { + pszFormat = L""; + } + } + + if (SUCCEEDED(hr)) + { + if (cchDest == 0) + { + pszDestEnd = pszDest; + cchRemaining = 0; + + // only fail if there was actually a non-empty format string + if (*pszFormat != L'\0') + { + if (pszDest == NULL) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + } + } + else + { + int iRet; + size_t cchMax; + + // leave the last space for the null terminator + cchMax = cchDest - 1; + + iRet = _vsnwprintf(pszDest, cchMax, pszFormat, argList); + // ASSERT((iRet < 0) || (((size_t)iRet) <= cchMax)); + + if ((iRet < 0) || (((size_t)iRet) > cchMax)) + { + // we have truncated pszDest + pszDestEnd = pszDest + cchMax; + cchRemaining = 1; + + // need to null terminate the string + *pszDestEnd = L'\0'; + + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + else if (((size_t)iRet) == cchMax) + { + // string fit perfectly + pszDestEnd = pszDest + cchMax; + cchRemaining = 1; + + // need to null terminate the string + *pszDestEnd = L'\0'; + } + else if (((size_t)iRet) < cchMax) + { + // there is extra room + 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; + + // null terminate the end of the string + *pszDestEnd = L'\0'; + } + } + + if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) + { + if (cchDest > 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + // null terminate the beginning of the string + *pszDestEnd = L'\0'; + } + } + } + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (ppszDestEnd) + { + *ppszDestEnd = pszDestEnd; + } + + if (pcchRemaining) + { + *pcchRemaining = cchRemaining; + } + } + + return hr; +} + +STRSAFEAPI StringLengthWorkerA(const char* psz, size_t cchMax, size_t* pcch) +{ + HRESULT hr = S_OK; + size_t cchMaxPrev = cchMax; + + while (cchMax && (*psz != '\0')) + { + psz++; + cchMax--; + } + + if (cchMax == 0) + { + // the string is longer than cchMax + hr = STRSAFE_E_INVALID_PARAMETER; + } + + if (SUCCEEDED(hr) && pcch) + { + *pcch = cchMaxPrev - cchMax; + } + + return hr; +} + +STRSAFEAPI StringLengthWorkerW(const wchar_t* psz, size_t cchMax, size_t* pcch) +{ + HRESULT hr = S_OK; + size_t cchMaxPrev = cchMax; + + while (cchMax && (*psz != L'\0')) + { + psz++; + cchMax--; + } + + if (cchMax == 0) + { + // the string is longer than cchMax + hr = STRSAFE_E_INVALID_PARAMETER; + } + + if (SUCCEEDED(hr) && pcch) + { + *pcch = cchMaxPrev - cchMax; + } + + return hr; +} +#endif // STRSAFE_INLINE + +#ifndef STRSAFE_LIB_IMPL +STRSAFE_INLINE_API StringGetsExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr = S_OK; + char* pszDestEnd = pszDest; + size_t cchRemaining = 0; + + // ASSERT(cbDest == (cchDest * sizeof(char)) || + // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char))); + + // only accept valid flags + if (dwFlags & (~STRSAFE_VALID_FLAGS)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + if (dwFlags & STRSAFE_IGNORE_NULLS) + { + if (pszDest == NULL) + { + if ((cchDest != 0) || (cbDest != 0)) + { + // NULL pszDest and non-zero cchDest/cbDest is invalid + 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 + { + char ch; + + pszDestEnd = pszDest; + cchRemaining = cchDest; + + while ((cchRemaining > 1) && (ch = (char)getc(stdin)) != '\n') + { + if (ch == EOF) + { + if (pszDestEnd == pszDest) + { + // we failed to read anything from stdin + hr = STRSAFE_E_END_OF_FILE; + } + break; + } + + *pszDestEnd = ch; + + pszDestEnd++; + cchRemaining--; + } + + if (cchRemaining > 0) + { + // there is extra room + 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; + + // null terminate the end of the string + *pszDestEnd = '\0'; + } + } + + if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) + { + if (cchDest > 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + // null terminate the beginning of the string + *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(wchar_t* pszDest, size_t cchDest, size_t cbDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr = S_OK; + wchar_t* pszDestEnd = pszDest; + size_t cchRemaining = 0; + + // ASSERT(cbDest == (cchDest * sizeof(char)) || + // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char))); + + // only accept valid flags + if (dwFlags & (~STRSAFE_VALID_FLAGS)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + if (dwFlags & STRSAFE_IGNORE_NULLS) + { + if (pszDest == NULL) + { + if ((cchDest != 0) || (cbDest != 0)) + { + // NULL pszDest and non-zero cchDest/cbDest is invalid + 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 + { + wchar_t ch; + + pszDestEnd = pszDest; + cchRemaining = cchDest; + + while ((cchRemaining > 1) && (ch = (wchar_t)getwc(stdin)) != L'\n') + { + if (ch == EOF) + { + if (pszDestEnd == pszDest) + { + // we failed to read anything from stdin + hr = STRSAFE_E_END_OF_FILE; + } + break; + } + + *pszDestEnd = ch; + + pszDestEnd++; + cchRemaining--; + } + + if (cchRemaining > 0) + { + // there is extra room + 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; + + // null terminate the end of the string + *pszDestEnd = L'\0'; + } + } + + if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) + { + if (cchDest > 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + // null terminate the beginning of the string + *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 // !STRSAFE_LIB_IMPL + + +// Do not call these functions, they are worker functions for internal use within this file +#ifdef DEPRECATE_SUPPORTED +#pragma deprecated(StringCopyWorkerA) +#pragma deprecated(StringCopyWorkerW) +#pragma deprecated(StringCopyExWorkerA) +#pragma deprecated(StringCopyExWorkerW) +#pragma deprecated(StringCatWorkerA) +#pragma deprecated(StringCatWorkerW) +#pragma deprecated(StringCatExWorkerA) +#pragma deprecated(StringCatExWorkerW) +#pragma deprecated(StringCatNWorkerA) +#pragma deprecated(StringCatNWorkerW) +#pragma deprecated(StringCatNExWorkerA) +#pragma deprecated(StringCatNExWorkerW) +#pragma deprecated(StringVPrintfWorkerA) +#pragma deprecated(StringVPrintfWorkerW) +#pragma deprecated(StringVPrintfExWorkerA) +#pragma deprecated(StringVPrintfExWorkerW) +#pragma deprecated(StringLengthWorkerA) +#pragma deprecated(StringLengthWorkerW) +#else +#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; +#endif // !DEPRECATE_SUPPORTED + + +#ifndef STRSAFE_NO_DEPRECATE +// Deprecate all of the unsafe functions to generate compiletime errors. If you do not want +// this then you can #define STRSAFE_NO_DEPRECATE before including this file. +#ifdef DEPRECATE_SUPPORTED + +// First all the names that are a/w variants (or shouldn't be #defined by now anyway). +#pragma deprecated(lstrcpyA) +#pragma deprecated(lstrcpyW) +#pragma deprecated(lstrcatA) +#pragma deprecated(lstrcatW) +#pragma deprecated(wsprintfA) +#pragma deprecated(wsprintfW) + +#pragma deprecated(StrCpyW) +#pragma deprecated(StrCatW) +#pragma deprecated(StrNCatA) +#pragma deprecated(StrNCatW) +#pragma deprecated(StrCatNA) +#pragma deprecated(StrCatNW) +#pragma deprecated(wvsprintfA) +#pragma deprecated(wvsprintfW) + +#pragma deprecated(strcpy) +#pragma deprecated(wcscpy) +#pragma deprecated(strcat) +#pragma deprecated(wcscat) +#pragma deprecated(sprintf) +#pragma deprecated(swprintf) +#pragma deprecated(vsprintf) +#pragma deprecated(vswprintf) +#pragma deprecated(_snprintf) +#pragma deprecated(_snwprintf) +#pragma deprecated(_vsnprintf) +#pragma deprecated(_vsnwprintf) +#pragma deprecated(gets) +#pragma deprecated(_getws) + +// Then all the windows.h names - we need to undef and redef based on UNICODE setting +#undef lstrcpy +#undef lstrcat +#undef wsprintf +#undef wvsprintf +#pragma deprecated(lstrcpy) +#pragma deprecated(lstrcat) +#pragma deprecated(wsprintf) +#pragma deprecated(wvsprintf) +#ifdef UNICODE +#define lstrcpy lstrcpyW +#define lstrcat lstrcatW +#define wsprintf wsprintfW +#define wvsprintf wvsprintfW +#else +#define lstrcpy lstrcpyA +#define lstrcat lstrcatA +#define wsprintf wsprintfA +#define wvsprintf wvsprintfA +#endif + +// Then the shlwapi names - they key off UNICODE also. +#undef StrCpyA +#undef StrCpy +#undef StrCatA +#undef StrCat +#undef StrNCat +#undef StrCatN +#pragma deprecated(StrCpyA) +#pragma deprecated(StrCatA) +#pragma deprecated(StrCatN) +#pragma deprecated(StrCpy) +#pragma deprecated(StrCat) +#pragma deprecated(StrNCat) +#define StrCpyA lstrcpyA +#define StrCatA lstrcatA +#define StrCatN StrNCat +#ifdef UNICODE +#define StrCpy StrCpyW +#define StrCat StrCatW +#define StrNCat StrNCatW +#else +#define StrCpy lstrcpyA +#define StrCat lstrcatA +#define StrNCat StrNCatA +#endif + +// Then all the CRT names - we need to undef/redef based on _UNICODE value. +#undef _tcscpy +#undef _ftcscpy +#undef _tcscat +#undef _ftcscat +#undef _stprintf +#undef _sntprintf +#undef _vstprintf +#undef _vsntprintf +#undef _getts +#pragma deprecated(_tcscpy) +#pragma deprecated(_ftcscpy) +#pragma deprecated(_tcscat) +#pragma deprecated(_ftcscat) +#pragma deprecated(_stprintf) +#pragma deprecated(_sntprintf) +#pragma deprecated(_vstprintf) +#pragma deprecated(_vsntprintf) +#pragma deprecated(_getts) +#ifdef _UNICODE +#define _tcscpy wcscpy +#define _ftcscpy wcscpy +#define _tcscat wcscat +#define _ftcscat wcscat +#define _stprintf swprintf +#define _sntprintf _snwprintf +#define _vstprintf vswprintf +#define _vsntprintf _vsnwprintf +#define _getts _getws +#else +#define _tcscpy strcpy +#define _ftcscpy strcpy +#define _tcscat strcat +#define _ftcscat strcat +#define _stprintf sprintf +#define _sntprintf _snprintf +#define _vstprintf vsprintf +#define _vsntprintf _vsnprintf +#define _getts gets +#endif + +#else // DEPRECATE_SUPPORTED + +#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 // !DEPRECATE_SUPPORTED +#endif // !STRSAFE_NO_DEPRECATE + +#ifdef _NTSTRSAFE_H_INCLUDED_ +#pragma warning(pop) +#endif // _NTSTRSAFE_H_INCLUDED_ + +#endif // _STRSAFE_H_INCLUDED_ diff --git a/cpp/Pipe/src/pipe.c b/cpp/Pipe/src/pipe.c new file mode 100644 index 0000000..c83c76d --- /dev/null +++ b/cpp/Pipe/src/pipe.c @@ -0,0 +1,262 @@ +#include +#include +#include +#include "pipe.h" + +#define DEBUG 0 + +JNIEXPORT jint JNICALL Java_pipe_Pipes_CreateNamedPipe +( + JNIEnv *env, + jclass className, + jstring sPipeName, + jint dwOpenMode, + jint dwPipeMode, + jint nMaxInstances, + jint nOutBufferSize, + jint nInBufferSize, + jint nDefaultTimeOut, + jint lpSecurityAttributes + ) +{ + HANDLE pipeHandler; + LPCSTR pipeName; + pipeName = (*env)->GetStringUTFChars(env, sPipeName, NULL); + if (pipeName == NULL) + return -1; + + if (DEBUG) + { + printf("Native: Pipe Name %s\n", pipeName); + printf("Native: dwOpenMode %d\n", dwOpenMode); + printf("Native: dwPipeMode %d\n", dwPipeMode); + printf("Native: nMaxInstances %d\n", nMaxInstances); + printf("Native: nOutBufferSize %d\n", nOutBufferSize); + printf("Native: nInBufferSize %d\n", nInBufferSize); + printf("Native: nDefaultTimeOut %d\n", nDefaultTimeOut); + } + + pipeHandler = CreateNamedPipe((LPCSTR)pipeName, dwOpenMode, dwPipeMode, nMaxInstances, nOutBufferSize, nInBufferSize, + nDefaultTimeOut, (LPSECURITY_ATTRIBUTES) lpSecurityAttributes); + + (*env)->ReleaseStringUTFChars(env, sPipeName, pipeName); + return (jint) pipeHandler; +} + +JNIEXPORT jboolean JNICALL Java_pipe_Pipes_ConnectNamedPipe +( + JNIEnv *env, + jclass className, + jint hNamedPipe, + jint lpOverlapped + ) +{ + BOOL fConnected; + HANDLE pipeHandler = (HANDLE) hNamedPipe; + fConnected = ConnectNamedPipe(pipeHandler, (LPOVERLAPPED) lpOverlapped); + return fConnected; +} + +JNIEXPORT jint JNICALL Java_pipe_Pipes_GetLastError +( + JNIEnv *env, + jclass className + ) +{ + DWORD errorNumber = GetLastError(); + return (jint) errorNumber; +} + +JNIEXPORT jboolean JNICALL Java_pipe_Pipes_CloseHandle +( + JNIEnv *env, + jclass className, + jint hNamedPipe + ) +{ + BOOL result; + HANDLE pipeHandler = (HANDLE) hNamedPipe; + result = CloseHandle(pipeHandler); + return result; +} + +JNIEXPORT jbyteArray JNICALL Java_pipe_Pipes_ReadFile +( + JNIEnv *env, + jclass className, + jint hNamedPipe, + jint nNumberOfBytesToRead + ) +{ + int bytesRead = 0; + BOOL result; + HANDLE pipeHandler = (HANDLE) hNamedPipe; + LPVOID buffer; + jbyteArray lpBuffer; + + buffer = (LPVOID)LocalAlloc(LMEM_ZEROINIT, nNumberOfBytesToRead); + + if (DEBUG) + { + printf("Native: Before ReadFile pipeHandler %d nNumberOfBytesToRead %d\n", pipeHandler, nNumberOfBytesToRead); + } + result = ReadFile(pipeHandler, (LPVOID) buffer, (DWORD) nNumberOfBytesToRead, &bytesRead, (LPOVERLAPPED) 0); + if (result) + { + lpBuffer = (*env)->NewByteArray(env, (jsize) bytesRead); + (*env)->SetByteArrayRegion(env, lpBuffer, 0, (jsize) bytesRead, (jbyte *) buffer); + } else + bytesRead = 0; + + LocalFree(buffer); + + if (DEBUG) + { + printf("Native: After ReadFile BytesRead %d\n", bytesRead); + } + return lpBuffer; +} + +JNIEXPORT jint JNICALL Java_pipe_Pipes_WriteFile +( + JNIEnv *env, + jclass className, + jint hNamedPipe, + jbyteArray lpBuffer, + jint nNumberOfBytesToWrite + ) +{ + int bytesWritten = 0; + BOOL result; + HANDLE pipeHandler = (HANDLE) hNamedPipe; + LPVOID buffer; + + buffer = (LPVOID)LocalAlloc(LMEM_ZEROINIT, nNumberOfBytesToWrite); + + (*env)->GetByteArrayRegion(env, lpBuffer, 0, nNumberOfBytesToWrite, buffer); + result = WriteFile(pipeHandler, buffer, (DWORD) nNumberOfBytesToWrite, (LPDWORD) &bytesWritten, (LPOVERLAPPED) 0); + LocalFree(buffer); + + if (DEBUG) + { + printf("Native: After WriteFile BytesReadWritten %d\n", bytesWritten); + } + + if (!result) + { + if (GetLastError() != ERROR_IO_PENDING) + result = 0; + else + result = 1; + } + if (!result) + { + bytesWritten = -1; + } + return bytesWritten; +} + +JNIEXPORT jboolean JNICALL Java_pipe_Pipes_FlushFileBuffers +( + JNIEnv *env, + jclass className, + jint hNamedPipe + ) +{ + BOOL result; + HANDLE pipeHandler = (HANDLE) hNamedPipe; + result = FlushFileBuffers(pipeHandler); + return result; +} + +JNIEXPORT jboolean JNICALL Java_pipe_Pipes_DisconnectNamedPipe +( + JNIEnv *env, + jclass className, + jint hNamedPipe + ) +{ + BOOL result; + HANDLE pipeHandler = (HANDLE) hNamedPipe; + result = DisconnectNamedPipe(pipeHandler); + return result; +} + +JNIEXPORT jint JNICALL Java_pipe_Pipes_CreateFile +( + JNIEnv *env, + jclass className, + jstring lpFileName, + jint dwDesiredAccess, + jint dwShareMode, + jint lpSecurityAttributes, + jint dwCreationDisposition, + jint dwFlagsAndAttributes, + jint hTemplateFile + ) +{ + HANDLE pipeHandler; + const jbyte *fileName; + fileName = (*env)->GetStringUTFChars(env, lpFileName, NULL); + if (fileName == NULL) + return -1; + pipeHandler = CreateFile((LPCSTR) fileName, (DWORD) dwDesiredAccess, (DWORD) dwShareMode, + (LPSECURITY_ATTRIBUTES) lpSecurityAttributes, (DWORD) dwCreationDisposition, (DWORD) dwFlagsAndAttributes, (HANDLE) hTemplateFile); + return (jint) pipeHandler; +} + +JNIEXPORT jboolean JNICALL Java_pipe_Pipes_WaitNamedPipe +( + JNIEnv *env, + jclass className, + jstring lpNamedPipeName, + jint nTimeOut + ) +{ + BOOL result; + const jbyte *pipeName; + pipeName = (*env)->GetStringUTFChars(env, lpNamedPipeName, NULL); + if (pipeName == NULL) + return 0; + result = WaitNamedPipe((LPCSTR) pipeName, (DWORD) nTimeOut); + return result; +} + +JNIEXPORT jstring JNICALL Java_pipe_Pipes_FormatMessage +( + JNIEnv *env, + jclass className, + jint errorCode +) +{ + LPVOID lpMsgBuf; + LPVOID lpDisplayBuf; + DWORD dw = (DWORD) errorCode; + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + dw, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, + 0, NULL ); + + lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, + (lstrlen((LPCTSTR)lpMsgBuf) + 40) * sizeof(TCHAR)); + StringCchPrintf((LPTSTR)lpDisplayBuf, LocalSize(lpDisplayBuf) / sizeof(TCHAR), + TEXT("Failed with error %d: %s"), dw, lpMsgBuf); + return (jstring) (*env)->NewStringUTF(env, lpDisplayBuf); +} + +JNIEXPORT void JNICALL Java_pipe_Pipes_Print(JNIEnv *env, jclass className, jstring lpMsgBuf) +{ + const jbyte *str; + str = (*env)->GetStringUTFChars(env, lpMsgBuf, NULL); + if (str == NULL) + return; + printf("Native: %s\n", str); + (*env)->ReleaseStringUTFChars(env, lpMsgBuf, str); + return; +} diff --git a/cpp/Pipe/src/pipe.h b/cpp/Pipe/src/pipe.h new file mode 100644 index 0000000..4687162 --- /dev/null +++ b/cpp/Pipe/src/pipe.h @@ -0,0 +1,109 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class Pipes */ + +#ifndef _Included_pipe +#define _Included_pipe +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: Pipes + * Method: CreateNamedPipe + * Signature: (Ljava/lang/String;IIIIIII)I + */ +JNIEXPORT jint JNICALL Java_pipe_Pipes_CreateNamedPipe + (JNIEnv *, jclass, jstring, jint, jint, jint, jint, jint, jint, jint); + +/* + * Class: Pipes + * Method: ConnectNamedPipe + * Signature: (II)Z + */ +JNIEXPORT jboolean JNICALL Java_pipe_Pipes_ConnectNamedPipe + (JNIEnv *, jclass, jint, jint); + +/* + * Class: Pipes + * Method: GetLastError + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_pipe_Pipes_GetLastError + (JNIEnv *, jclass); + +/* + * Class: Pipes + * Method: CloseHandle + * Signature: (I)Z + */ +JNIEXPORT jboolean JNICALL Java_pipe_Pipes_CloseHandle + (JNIEnv *, jclass, jint); + +/* + * Class: Pipes + * Method: ReadFile + * Signature: (II)[B + */ +JNIEXPORT jbyteArray JNICALL Java_pipe_Pipes_ReadFile + (JNIEnv *, jclass, jint, jint); + +/* + * Class: Pipes + * Method: WriteFile + * Signature: (I[BI)I + */ +JNIEXPORT jint JNICALL Java_pipe_Pipes_WriteFile + (JNIEnv *, jclass, jint, jbyteArray, jint); + +/* + * Class: Pipes + * Method: FlushFileBuffers + * Signature: (I)Z + */ +JNIEXPORT jboolean JNICALL Java_pipe_Pipes_FlushFileBuffers + (JNIEnv *, jclass, jint); + +/* + * Class: Pipes + * Method: DisconnectNamedPipe + * Signature: (I)Z + */ +JNIEXPORT jboolean JNICALL Java_pipe_Pipes_DisconnectNamedPipe + (JNIEnv *, jclass, jint); + +/* + * Class: Pipes + * Method: CreateFile + * Signature: (Ljava/lang/String;IIIIII)I + */ +JNIEXPORT jint JNICALL Java_pipe_Pipes_CreateFile + (JNIEnv *, jclass, jstring, jint, jint, jint, jint, jint, jint); + +/* + * Class: Pipes + * Method: WaitNamedPipe + * Signature: (Ljava/lang/String;I)Z + */ +JNIEXPORT jboolean JNICALL Java_pipe_Pipes_WaitNamedPipe + (JNIEnv *, jclass, jstring, jint); + +/* + * Class: Pipes + * Method: FormatMessage + * Signature: (I)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_pipe_Pipes_FormatMessage + (JNIEnv *, jclass, jint); + +/* + * Class: Pipes + * Method: Print + * Signature: (Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_pipe_Pipes_Print + (JNIEnv *, jclass, jstring); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/cpp/pipe/.cproject b/cpp/pipe/.cproject new file mode 100644 index 0000000..7e01e41 --- /dev/null +++ b/cpp/pipe/.cproject @@ -0,0 +1,154 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cpp/pipe/.project b/cpp/pipe/.project new file mode 100644 index 0000000..511c69c --- /dev/null +++ b/cpp/pipe/.project @@ -0,0 +1,27 @@ + + + Pipe + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.core.ccnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/cpp/pipe/include/strsafe.h b/cpp/pipe/include/strsafe.h new file mode 100644 index 0000000..061b3c4 --- /dev/null +++ b/cpp/pipe/include/strsafe.h @@ -0,0 +1,6611 @@ +/****************************************************************** +* * +* strsafe.h -- This module defines safer C library string * +* routine replacements. These are meant to make C * +* a bit more safe in reference to security and * +* robustness * +* * +* Copyright (c) Microsoft Corp. All rights reserved. * +* * +******************************************************************/ +#ifndef _STRSAFE_H_INCLUDED_ +#define _STRSAFE_H_INCLUDED_ +#pragma once + +#include // for _vsnprintf, _vsnwprintf, getc, getwc +#include // for memset +#include // for va_start, etc. + + +#ifndef _SIZE_T_DEFINED +#ifdef _WIN64 +typedef unsigned __int64 size_t; +#else +typedef __w64 unsigned int size_t; +#endif // !_WIN64 +#define _SIZE_T_DEFINED +#endif // !_SIZE_T_DEFINED + +#if !defined(_WCHAR_T_DEFINED) && !defined(_NATIVE_WCHAR_T_DEFINED) +typedef unsigned short wchar_t; +#define _WCHAR_T_DEFINED +#endif + +#ifndef _HRESULT_DEFINED +#define _HRESULT_DEFINED +typedef long HRESULT; +#endif // !_HRESULT_DEFINED + +#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 + +#ifdef __cplusplus +#define _STRSAFE_EXTERN_C extern "C" +#else +#define _STRSAFE_EXTERN_C extern +#endif + +// If you do not want to use these functions inline (and instead want to link w/ strsafe.lib), then +// #define STRSAFE_LIB before including this header file. +#if defined(STRSAFE_LIB) +#define STRSAFEAPI _STRSAFE_EXTERN_C HRESULT __stdcall +#pragma comment(lib, "strsafe.lib") +#elif defined(STRSAFE_LIB_IMPL) +#define STRSAFEAPI _STRSAFE_EXTERN_C HRESULT __stdcall +#else +#define STRSAFEAPI __inline HRESULT __stdcall +#define STRSAFE_INLINE +#endif + +// Some functions always run inline because they use stdin and we want to avoid building multiple +// versions of strsafe lib depending on if you use msvcrt, libcmt, etc. +#define STRSAFE_INLINE_API __inline HRESULT __stdcall + +// The user can request no "Cb" or no "Cch" fuctions, but not both! +#if defined(STRSAFE_NO_CB_FUNCTIONS) && defined(STRSAFE_NO_CCH_FUNCTIONS) +#error cannot specify both STRSAFE_NO_CB_FUNCTIONS and STRSAFE_NO_CCH_FUNCTIONS !! +#endif + +// This should only be defined when we are building strsafe.lib +#ifdef STRSAFE_LIB_IMPL +#define STRSAFE_INLINE +#endif + + +// If both strsafe.h and ntstrsafe.h are included, only use definitions from one. +#ifndef _NTSTRSAFE_H_INCLUDED_ + +#define STRSAFE_MAX_CCH 2147483647 // max # of characters we support (same as INT_MAX) + +// Flags for controling the Ex functions +// +// STRSAFE_FILL_BYTE(0xFF) 0x000000FF // bottom byte specifies fill pattern +#define STRSAFE_IGNORE_NULLS 0x00000100 // treat null as TEXT("") -- don't fault on NULL buffers +#define STRSAFE_FILL_BEHIND_NULL 0x00000200 // fill in extra space behind the null terminator +#define STRSAFE_FILL_ON_FAILURE 0x00000400 // on failure, overwrite pszDest with fill pattern and null terminate it +#define STRSAFE_NULL_ON_FAILURE 0x00000800 // on failure, set *pszDest = TEXT('\0') +#define STRSAFE_NO_TRUNCATION 0x00001000 // instead of returning a truncated result, copy/append nothing to pszDest and null terminate it + +#define STRSAFE_VALID_FLAGS (0x000000FF | STRSAFE_IGNORE_NULLS | STRSAFE_FILL_BEHIND_NULL | STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION) + +// helper macro to set the fill character and specify buffer filling +#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 // _NTSTRSAFE_H_INCLUDED_ + +// STRSAFE error return codes +// +#define STRSAFE_E_INSUFFICIENT_BUFFER ((HRESULT)0x8007007AL) // 0x7A = 122L = ERROR_INSUFFICIENT_BUFFER +#define STRSAFE_E_INVALID_PARAMETER ((HRESULT)0x80070057L) // 0x57 = 87L = ERROR_INVALID_PARAMETER +#define STRSAFE_E_END_OF_FILE ((HRESULT)0x80070026L) // 0x26 = 38L = ERROR_HANDLE_EOF + +// prototypes for the worker functions +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCopyWorkerA(char* pszDest, size_t cchDest, const char* pszSrc); +STRSAFEAPI StringCopyWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc); +STRSAFEAPI StringCopyExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFEAPI StringCopyExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFEAPI StringCopyNWorkerA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc); +STRSAFEAPI StringCopyNWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchSrc); +STRSAFEAPI StringCopyNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, size_t cchSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFEAPI StringCopyNExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, const wchar_t* pszSrc, size_t cchSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFEAPI StringCatWorkerA(char* pszDest, size_t cchDest, const char* pszSrc); +STRSAFEAPI StringCatWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc); +STRSAFEAPI StringCatExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFEAPI StringCatExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFEAPI StringCatNWorkerA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend); +STRSAFEAPI StringCatNWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchMaxAppend); +STRSAFEAPI StringCatNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, size_t cchMaxAppend, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFEAPI StringCatNExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, const wchar_t* pszSrc, size_t cchMaxAppend, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFEAPI StringVPrintfWorkerA(char* pszDest, size_t cchDest, const char* pszFormat, va_list argList); +STRSAFEAPI StringVPrintfWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszFormat, va_list argList); +STRSAFEAPI StringVPrintfExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList); +STRSAFEAPI StringVPrintfExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const wchar_t* pszFormat, va_list argList); +STRSAFEAPI StringLengthWorkerA(const char* psz, size_t cchMax, size_t* pcch); +STRSAFEAPI StringLengthWorkerW(const wchar_t* psz, size_t cchMax, size_t* pcch); +#endif // STRSAFE_INLINE + +#ifndef STRSAFE_LIB_IMPL +// these functions are always inline +STRSAFE_INLINE_API StringGetsExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFE_INLINE_API StringGetsExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +#endif + +#ifdef _NTSTRSAFE_H_INCLUDED_ +#pragma warning(push) +#pragma warning(disable : 4995) +#endif // _NTSTRSAFE_H_INCLUDED_ + + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI +StringCchCopy( + OUT LPTSTR pszDest, + IN size_t cchDest, + IN LPCTSTR pszSrc + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'strcpy'. + The size of the destination buffer (in characters) is a parameter and + this function will not write past the end of this buffer and it will + ALWAYS null terminate the destination buffer (unless it is zero length). + + This routine is not a replacement for strncpy. That function will pad the + destination string with extra null termination characters if the count is + greater than the length of the source string, and it will fail to null + terminate the destination string if the source string length is greater + than or equal to the count. You can not blindly use this instead of strncpy: + it is common for code to use it to "patch" strings and you would introduce + errors if the code started null terminating in the middle of the string. + + This function returns a hresult, and not a pointer. It returns + S_OK if the string was copied without truncation and null terminated, + otherwise it will return a failure code. In failure cases as much of + pszSrc will be copied to pszDest as possible, and pszDest will be null + terminated. + +Arguments: + + pszDest - destination string + + cchDest - size of destination buffer in characters. + length must be = (_tcslen(src) + 1) to hold all of the + source including the null terminator + + pszSrc - source string which must be null terminated + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL. See StringCchCopyEx if you require + the handling of NULL values. + +Return Value: + + S_OK - if there was source data and it was all copied and the + resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the copy + operation failed due to insufficient space. When this + error occurs, the destination buffer is modified to + contain a truncated version of the ideal result and is + null terminated. This is useful for situations where + truncation is ok + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function. + +--*/ + +STRSAFEAPI StringCchCopyA(char* pszDest, size_t cchDest, const char* pszSrc); +STRSAFEAPI StringCchCopyW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc); +#ifdef UNICODE +#define StringCchCopy StringCchCopyW +#else +#define StringCchCopy StringCchCopyA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCchCopyA(char* pszDest, size_t cchDest, const char* pszSrc) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCopyWorkerA(pszDest, cchDest, pszSrc); + } + + return hr; +} + +STRSAFEAPI StringCchCopyW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCopyWorkerW(pszDest, cchDest, pszSrc); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CCH_FUNCTIONS + + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI +StringCbCopy( + OUT LPTSTR pszDest, + IN size_t cbDest, + IN LPCTSTR pszSrc + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'strcpy'. + The size of the destination buffer (in bytes) is a parameter and this + function will not write past the end of this buffer and it will ALWAYS + null terminate the destination buffer (unless it is zero length). + + This routine is not a replacement for strncpy. That function will pad the + destination string with extra null termination characters if the count is + greater than the length of the source string, and it will fail to null + terminate the destination string if the source string length is greater + than or equal to the count. You can not blindly use this instead of strncpy: + it is common for code to use it to "patch" strings and you would introduce + errors if the code started null terminating in the middle of the string. + + This function returns a hresult, and not a pointer. It returns + S_OK if the string was copied without truncation and null terminated, + otherwise it will return a failure code. In failure cases as much of pszSrc + will be copied to pszDest as possible, and pszDest will be null terminated. + +Arguments: + + pszDest - destination string + + cbDest - size of destination buffer in bytes. + length must be = ((_tcslen(src) + 1) * sizeof(TCHAR)) to + hold all of the source including the null terminator + + pszSrc - source string which must be null terminated + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL. See StringCbCopyEx if you require + the handling of NULL values. + +Return Value: + + S_OK - if there was source data and it was all copied and the + resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the copy + operation failed due to insufficient space. When this + error occurs, the destination buffer is modified to + contain a truncated version of the ideal result and is + null terminated. This is useful for situations where + truncation is ok + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function. + +--*/ + +STRSAFEAPI StringCbCopyA(char* pszDest, size_t cbDest, const char* pszSrc); +STRSAFEAPI StringCbCopyW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc); +#ifdef UNICODE +#define StringCbCopy StringCbCopyW +#else +#define StringCbCopy StringCbCopyA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCbCopyA(char* pszDest, size_t cbDest, const char* pszSrc) +{ + HRESULT hr; + size_t cchDest; + + // convert to count of characters + cchDest = cbDest / sizeof(char); + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCopyWorkerA(pszDest, cchDest, pszSrc); + } + + return hr; +} + +STRSAFEAPI StringCbCopyW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc) +{ + HRESULT hr; + size_t cchDest; + + // convert to count of characters + cchDest = cbDest / sizeof(wchar_t); + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCopyWorkerW(pszDest, cchDest, pszSrc); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CB_FUNCTIONS + + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI +StringCchCopyEx( + OUT LPTSTR pszDest OPTIONAL, + IN size_t cchDest, + IN LPCTSTR pszSrc OPTIONAL, + OUT LPTSTR* ppszDestEnd OPTIONAL, + OUT size_t* pcchRemaining OPTIONAL, + IN DWORD dwFlags + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'strcpy' with + some additional parameters. In addition to functionality provided by + StringCchCopy, this routine also returns a pointer to the end of the + destination string and the number of characters left in the destination string + including the null terminator. The flags parameter allows additional controls. + +Arguments: + + pszDest - destination string + + cchDest - size of destination buffer in characters. + length must be = (_tcslen(pszSrc) + 1) to hold all of + the source including the null terminator + + pszSrc - source string which must be null terminated + + ppszDestEnd - if ppszDestEnd is non-null, the function will return a + pointer to the end of the destination string. If the + function copied any data, the result will point to the + null termination character + + pcchRemaining - if pcchRemaining is non-null, the function will return the + number of characters left in the destination string, + including the null terminator + + dwFlags - controls some details of the string copy: + + STRSAFE_FILL_BEHIND_NULL + if the function succeeds, the low byte of dwFlags will be + used to fill the uninitialize part of destination buffer + behind the null terminator + + STRSAFE_IGNORE_NULLS + treat NULL string pointers like empty strings (TEXT("")). + this flag is useful for emulating functions like lstrcpy + + STRSAFE_FILL_ON_FAILURE + if the function fails, the low byte of dwFlags will be + used to fill all of the destination buffer, and it will + be null terminated. This will overwrite any truncated + string returned when the failure is + STRSAFE_E_INSUFFICIENT_BUFFER + + STRSAFE_NO_TRUNCATION / + STRSAFE_NULL_ON_FAILURE + if the function fails, the destination buffer will be set + to the empty string. This will overwrite any truncated string + returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER. + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag + is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc + may be NULL. An error may still be returned even though NULLS are ignored + due to insufficient space. + +Return Value: + + S_OK - if there was source data and it was all copied and the + resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the copy + operation failed due to insufficient space. When this + error occurs, the destination buffer is modified to + contain a truncated version of the ideal result and is + null terminated. This is useful for situations where + truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCchCopyExA(char* pszDest, size_t cchDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFEAPI StringCchCopyExW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +#ifdef UNICODE +#define StringCchCopyEx StringCchCopyExW +#else +#define StringCchCopyEx StringCchCopyExA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCchCopyExA(char* pszDest, size_t cchDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + + // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1 + cbDest = cchDest * sizeof(char); + + hr = StringCopyExWorkerA(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, pcchRemaining, dwFlags); + } + + return hr; +} + +STRSAFEAPI StringCchCopyExW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + + // safe to multiply cchDest * sizeof(wchar_t) since cchDest < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 + cbDest = cchDest * sizeof(wchar_t); + + hr = StringCopyExWorkerW(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, pcchRemaining, dwFlags); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CCH_FUNCTIONS + + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI +StringCbCopyEx( + OUT LPTSTR pszDest OPTIONAL, + IN size_t cbDest, + IN LPCTSTR pszSrc OPTIONAL, + OUT LPTSTR* ppszDestEnd OPTIONAL, + OUT size_t* pcbRemaining OPTIONAL, + IN DWORD dwFlags + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'strcpy' with + some additional parameters. In addition to functionality provided by + StringCbCopy, this routine also returns a pointer to the end of the + destination string and the number of bytes left in the destination string + including the null terminator. The flags parameter allows additional controls. + +Arguments: + + pszDest - destination string + + cbDest - size of destination buffer in bytes. + length must be ((_tcslen(pszSrc) + 1) * sizeof(TCHAR)) to + hold all of the source including the null terminator + + pszSrc - source string which must be null terminated + + ppszDestEnd - if ppszDestEnd is non-null, the function will return a + pointer to the end of the destination string. If the + function copied any data, the result will point to the + null termination character + + pcbRemaining - pcbRemaining is non-null,the function will return the + number of bytes left in the destination string, + including the null terminator + + dwFlags - controls some details of the string copy: + + STRSAFE_FILL_BEHIND_NULL + if the function succeeds, the low byte of dwFlags will be + used to fill the uninitialize part of destination buffer + behind the null terminator + + STRSAFE_IGNORE_NULLS + treat NULL string pointers like empty strings (TEXT("")). + this flag is useful for emulating functions like lstrcpy + + STRSAFE_FILL_ON_FAILURE + if the function fails, the low byte of dwFlags will be + used to fill all of the destination buffer, and it will + be null terminated. This will overwrite any truncated + string returned when the failure is + STRSAFE_E_INSUFFICIENT_BUFFER + + STRSAFE_NO_TRUNCATION / + STRSAFE_NULL_ON_FAILURE + if the function fails, the destination buffer will be set + to the empty string. This will overwrite any truncated string + returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER. + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag + is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc + may be NULL. An error may still be returned even though NULLS are ignored + due to insufficient space. + +Return Value: + + S_OK - if there was source data and it was all copied and the + resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the copy + operation failed due to insufficient space. When this + error occurs, the destination buffer is modified to + contain a truncated version of the ideal result and is + null terminated. This is useful for situations where + truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCbCopyExA(char* pszDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags); +STRSAFEAPI StringCbCopyExW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags); +#ifdef UNICODE +#define StringCbCopyEx StringCbCopyExW +#else +#define StringCbCopyEx StringCbCopyExA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCbCopyExA(char* pszDest, size_t cbDest, const char* pszSrc, char** 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) + { + // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1 + *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)); + } + } + + return hr; +} + +STRSAFEAPI StringCbCopyExW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, wchar_t** 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) + { + // safe to multiply cchRemaining * sizeof(wchar_t) since cchRemaining < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 + *pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)); + } + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CB_FUNCTIONS + + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI +StringCchCopyN( + OUT LPTSTR pszDest, + IN size_t cchDest, + IN LPCTSTR pszSrc, + IN size_t cchSrc + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'strncpy'. + The size of the destination buffer (in characters) is a parameter and + this function will not write past the end of this buffer and it will + ALWAYS null terminate the destination buffer (unless it is zero length). + + This routine is meant as a replacement for strncpy, but it does behave + differently. This function will not pad the destination buffer with extra + null termination characters if cchSrc is greater than the length of pszSrc. + + This function returns a hresult, and not a pointer. It returns + S_OK if the entire string or the first cchSrc characters were copied + without truncation and the resultant destination string was null terminated, + otherwise it will return a failure code. In failure cases as much of pszSrc + will be copied to pszDest as possible, and pszDest will be null terminated. + +Arguments: + + pszDest - destination string + + cchDest - size of destination buffer in characters. + length must be = (_tcslen(src) + 1) to hold all of the + source including the null terminator + + pszSrc - source string + + cchSrc - maximum number of characters to copy from source string, + not including the null terminator. + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL. See StringCchCopyNEx if you require + the handling of NULL values. + +Return Value: + + S_OK - if there was source data and it was all copied and the + resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the copy + operation failed due to insufficient space. When this + error occurs, the destination buffer is modified to + contain a truncated version of the ideal result and is + null terminated. This is useful for situations where + truncation is ok + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function. + +--*/ + +STRSAFEAPI StringCchCopyNA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc); +STRSAFEAPI StringCchCopyNW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchSrc); +#ifdef UNICODE +#define StringCchCopyN StringCchCopyNW +#else +#define StringCchCopyN StringCchCopyNA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCchCopyNA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc) +{ + HRESULT hr; + + if ((cchDest > STRSAFE_MAX_CCH) || + (cchSrc > STRSAFE_MAX_CCH)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCopyNWorkerA(pszDest, cchDest, pszSrc, cchSrc); + } + + return hr; +} + +STRSAFEAPI StringCchCopyNW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchSrc) +{ + HRESULT hr; + + if ((cchDest > STRSAFE_MAX_CCH) || + (cchSrc > STRSAFE_MAX_CCH)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCopyNWorkerW(pszDest, cchDest, pszSrc, cchSrc); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CCH_FUNCTIONS + + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI +StringCbCopyN( + OUT LPTSTR pszDest, + IN size_t cbDest, + IN LPCTSTR pszSrc, + IN size_t cbSrc + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'strncpy'. + The size of the destination buffer (in bytes) is a parameter and this + function will not write past the end of this buffer and it will ALWAYS + null terminate the destination buffer (unless it is zero length). + + This routine is meant as a replacement for strncpy, but it does behave + differently. This function will not pad the destination buffer with extra + null termination characters if cbSrc is greater than the size of pszSrc. + + This function returns a hresult, and not a pointer. It returns + S_OK if the entire string or the first cbSrc characters were + copied without truncation and the resultant destination string was null + terminated, otherwise it will return a failure code. In failure cases as + much of pszSrc will be copied to pszDest as possible, and pszDest will be + null terminated. + +Arguments: + + pszDest - destination string + + cbDest - size of destination buffer in bytes. + length must be = ((_tcslen(src) + 1) * sizeof(TCHAR)) to + hold all of the source including the null terminator + + pszSrc - source string + + cbSrc - maximum number of bytes to copy from source string, + not including the null terminator. + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL. See StringCbCopyEx if you require + the handling of NULL values. + +Return Value: + + S_OK - if there was source data and it was all copied and the + resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the copy + operation failed due to insufficient space. When this + error occurs, the destination buffer is modified to + contain a truncated version of the ideal result and is + null terminated. This is useful for situations where + truncation is ok + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function. + +--*/ + +STRSAFEAPI StringCbCopyNA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbSrc); +STRSAFEAPI StringCbCopyNW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, size_t cbSrc); +#ifdef UNICODE +#define StringCbCopyN StringCbCopyNW +#else +#define StringCbCopyN StringCbCopyNA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCbCopyNA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbSrc) +{ + HRESULT hr; + size_t cchDest; + size_t cchSrc; + + // convert to count of characters + cchDest = cbDest / sizeof(char); + cchSrc = cbSrc / sizeof(char); + + if ((cchDest > STRSAFE_MAX_CCH) || + (cchSrc > STRSAFE_MAX_CCH)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCopyNWorkerA(pszDest, cchDest, pszSrc, cchSrc); + } + + return hr; +} + +STRSAFEAPI StringCbCopyNW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, size_t cbSrc) +{ + HRESULT hr; + size_t cchDest; + size_t cchSrc; + + // convert to count of characters + cchDest = cbDest / sizeof(wchar_t); + cchSrc = cbSrc / sizeof(wchar_t); + + if ((cchDest > STRSAFE_MAX_CCH) || + (cchSrc > STRSAFE_MAX_CCH)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCopyNWorkerW(pszDest, cchDest, pszSrc, cchSrc); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CB_FUNCTIONS + + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI +StringCchCopyNEx( + OUT LPTSTR pszDest OPTIONAL, + IN size_t cchDest, + IN LPCTSTR pszSrc OPTIONAL, + IN size_t cchSrc, + OUT LPTSTR* ppszDestEnd OPTIONAL, + OUT size_t* pcchRemaining OPTIONAL, + IN DWORD dwFlags + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'strncpy' with + some additional parameters. In addition to functionality provided by + StringCchCopyN, this routine also returns a pointer to the end of the + destination string and the number of characters left in the destination + string including the null terminator. The flags parameter allows + additional controls. + + This routine is meant as a replacement for strncpy, but it does behave + differently. This function will not pad the destination buffer with extra + null termination characters if cchSrc is greater than the length of pszSrc. + +Arguments: + + pszDest - destination string + + cchDest - size of destination buffer in characters. + length must be = (_tcslen(pszSrc) + 1) to hold all of + the source including the null terminator + + pszSrc - source string + + cchSrc - maximum number of characters to copy from the source + string + + ppszDestEnd - if ppszDestEnd is non-null, the function will return a + pointer to the end of the destination string. If the + function copied any data, the result will point to the + null termination character + + pcchRemaining - if pcchRemaining is non-null, the function will return the + number of characters left in the destination string, + including the null terminator + + dwFlags - controls some details of the string copy: + + STRSAFE_FILL_BEHIND_NULL + if the function succeeds, the low byte of dwFlags will be + used to fill the uninitialize part of destination buffer + behind the null terminator + + STRSAFE_IGNORE_NULLS + treat NULL string pointers like empty strings (TEXT("")). + this flag is useful for emulating functions like lstrcpy + + STRSAFE_FILL_ON_FAILURE + if the function fails, the low byte of dwFlags will be + used to fill all of the destination buffer, and it will + be null terminated. This will overwrite any truncated + string returned when the failure is + STRSAFE_E_INSUFFICIENT_BUFFER + + STRSAFE_NO_TRUNCATION / + STRSAFE_NULL_ON_FAILURE + if the function fails, the destination buffer will be set + to the empty string. This will overwrite any truncated string + returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER. + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag + is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc + may be NULL. An error may still be returned even though NULLS are ignored + due to insufficient space. + +Return Value: + + S_OK - if there was source data and it was all copied and the + resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the copy + operation failed due to insufficient space. When this + error occurs, the destination buffer is modified to + contain a truncated version of the ideal result and is + null terminated. This is useful for situations where + truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCchCopyNExA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFEAPI StringCchCopyNExW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +#ifdef UNICODE +#define StringCchCopyNEx StringCchCopyNExW +#else +#define StringCchCopyNEx StringCchCopyNExA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCchCopyNExA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr; + + if ((cchDest > STRSAFE_MAX_CCH) || + (cchSrc > STRSAFE_MAX_CCH)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + + // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1 + cbDest = cchDest * sizeof(char); + + hr = StringCopyNExWorkerA(pszDest, cchDest, cbDest, pszSrc, cchSrc, ppszDestEnd, pcchRemaining, dwFlags); + } + + return hr; +} + +STRSAFEAPI StringCchCopyNExW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr; + + if ((cchDest > STRSAFE_MAX_CCH) || + (cchSrc > STRSAFE_MAX_CCH)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + + // safe to multiply cchDest * sizeof(wchar_t) since cchDest < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 + cbDest = cchDest * sizeof(wchar_t); + + hr = StringCopyNExWorkerW(pszDest, cchDest, cbDest, pszSrc, cchSrc, ppszDestEnd, pcchRemaining, dwFlags); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CCH_FUNCTIONS + + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI +StringCbCopyNEx( + OUT LPTSTR pszDest OPTIONAL, + IN size_t cbDest, + IN LPCTSTR pszSrc OPTIONAL, + IN size_t cbSrc, + OUT LPTSTR* ppszDestEnd OPTIONAL, + OUT size_t* pcbRemaining OPTIONAL, + IN DWORD dwFlags + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'strncpy' with + some additional parameters. In addition to functionality provided by + StringCbCopyN, this routine also returns a pointer to the end of the + destination string and the number of bytes left in the destination string + including the null terminator. The flags parameter allows additional controls. + + This routine is meant as a replacement for strncpy, but it does behave + differently. This function will not pad the destination buffer with extra + null termination characters if cbSrc is greater than the size of pszSrc. + +Arguments: + + pszDest - destination string + + cbDest - size of destination buffer in bytes. + length must be ((_tcslen(pszSrc) + 1) * sizeof(TCHAR)) to + hold all of the source including the null terminator + + pszSrc - source string + + cbSrc - maximum number of bytes to copy from source string + + ppszDestEnd - if ppszDestEnd is non-null, the function will return a + pointer to the end of the destination string. If the + function copied any data, the result will point to the + null termination character + + pcbRemaining - pcbRemaining is non-null,the function will return the + number of bytes left in the destination string, + including the null terminator + + dwFlags - controls some details of the string copy: + + STRSAFE_FILL_BEHIND_NULL + if the function succeeds, the low byte of dwFlags will be + used to fill the uninitialize part of destination buffer + behind the null terminator + + STRSAFE_IGNORE_NULLS + treat NULL string pointers like empty strings (TEXT("")). + this flag is useful for emulating functions like lstrcpy + + STRSAFE_FILL_ON_FAILURE + if the function fails, the low byte of dwFlags will be + used to fill all of the destination buffer, and it will + be null terminated. This will overwrite any truncated + string returned when the failure is + STRSAFE_E_INSUFFICIENT_BUFFER + + STRSAFE_NO_TRUNCATION / + STRSAFE_NULL_ON_FAILURE + if the function fails, the destination buffer will be set + to the empty string. This will overwrite any truncated string + returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER. + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag + is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc + may be NULL. An error may still be returned even though NULLS are ignored + due to insufficient space. + +Return Value: + + S_OK - if there was source data and it was all copied and the + resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the copy + operation failed due to insufficient space. When this + error occurs, the destination buffer is modified to + contain a truncated version of the ideal result and is + null terminated. This is useful for situations where + truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCbCopyNExA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags); +STRSAFEAPI StringCbCopyNExW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, size_t cbSrc, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags); +#ifdef UNICODE +#define StringCbCopyNEx StringCbCopyNExW +#else +#define StringCbCopyNEx StringCbCopyNExA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCbCopyNExA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags) +{ + HRESULT hr; + size_t cchDest; + size_t cchSrc; + size_t cchRemaining = 0; + + cchDest = cbDest / sizeof(char); + cchSrc = cbSrc / sizeof(char); + + if ((cchDest > STRSAFE_MAX_CCH) || + (cchSrc > STRSAFE_MAX_CCH)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCopyNExWorkerA(pszDest, cchDest, cbDest, pszSrc, cchSrc, ppszDestEnd, &cchRemaining, dwFlags); + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (pcbRemaining) + { + // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1 + *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)); + } + } + + return hr; +} + +STRSAFEAPI StringCbCopyNExW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, size_t cbSrc, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags) +{ + HRESULT hr; + size_t cchDest; + size_t cchSrc; + size_t cchRemaining = 0; + + cchDest = cbDest / sizeof(wchar_t); + cchSrc = cbSrc / sizeof(wchar_t); + + if ((cchDest > STRSAFE_MAX_CCH) || + (cchSrc > STRSAFE_MAX_CCH)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCopyNExWorkerW(pszDest, cchDest, cbDest, pszSrc, cchSrc, ppszDestEnd, &cchRemaining, dwFlags); + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (pcbRemaining) + { + // safe to multiply cchRemaining * sizeof(wchar_t) since cchRemaining < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 + *pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)); + } + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CB_FUNCTIONS + + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI +StringCchCat( + IN OUT LPTSTR pszDest, + IN size_t cchDest, + IN LPCTSTR pszSrc + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'strcat'. + The size of the destination buffer (in characters) is a parameter and this + function will not write past the end of this buffer and it will ALWAYS + null terminate the destination buffer (unless it is zero length). + + This function returns a hresult, and not a pointer. It returns + S_OK if the string was concatenated without truncation and null terminated, + otherwise it will return a failure code. In failure cases as much of pszSrc + will be appended to pszDest as possible, and pszDest will be null + terminated. + +Arguments: + + pszDest - destination string which must be null terminated + + cchDest - size of destination buffer in characters. + length must be = (_tcslen(pszDest) + _tcslen(pszSrc) + 1) + to hold all of the combine string plus the null + terminator + + pszSrc - source string which must be null terminated + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL. See StringCchCatEx if you require + the handling of NULL values. + +Return Value: + + S_OK - if there was source data and it was all concatenated and + the resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the operation + failed due to insufficient space. When this error occurs, + the destination buffer is modified to contain a truncated + version of the ideal result and is null terminated. This + is useful for situations where truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCchCatA(char* pszDest, size_t cchDest, const char* pszSrc); +STRSAFEAPI StringCchCatW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc); +#ifdef UNICODE +#define StringCchCat StringCchCatW +#else +#define StringCchCat StringCchCatA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCchCatA(char* pszDest, size_t cchDest, const char* pszSrc) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCatWorkerA(pszDest, cchDest, pszSrc); + } + + return hr; +} + +STRSAFEAPI StringCchCatW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCatWorkerW(pszDest, cchDest, pszSrc); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CCH_FUNCTIONS + + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI +StringCbCat( + IN OUT LPTSTR pszDest, + IN size_t cbDest, + IN LPCTSTR pszSrc + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'strcat'. + The size of the destination buffer (in bytes) is a parameter and this + function will not write past the end of this buffer and it will ALWAYS + null terminate the destination buffer (unless it is zero length). + + This function returns a hresult, and not a pointer. It returns + S_OK if the string was concatenated without truncation and null terminated, + otherwise it will return a failure code. In failure cases as much of pszSrc + will be appended to pszDest as possible, and pszDest will be null + terminated. + +Arguments: + + pszDest - destination string which must be null terminated + + cbDest - size of destination buffer in bytes. + length must be = ((_tcslen(pszDest) + _tcslen(pszSrc) + 1) * sizeof(TCHAR) + to hold all of the combine string plus the null + terminator + + pszSrc - source string which must be null terminated + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL. See StringCbCatEx if you require + the handling of NULL values. + +Return Value: + + S_OK - if there was source data and it was all concatenated and + the resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the operation + failed due to insufficient space. When this error occurs, + the destination buffer is modified to contain a truncated + version of the ideal result and is null terminated. This + is useful for situations where truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCbCatA(char* pszDest, size_t cbDest, const char* pszSrc); +STRSAFEAPI StringCbCatW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc); +#ifdef UNICODE +#define StringCbCat StringCbCatW +#else +#define StringCbCat StringCbCatA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCbCatA(char* pszDest, size_t cbDest, const char* 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(wchar_t* pszDest, size_t cbDest, const wchar_t* 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 // STRSAFE_INLINE +#endif // !STRSAFE_NO_CB_FUNCTIONS + + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI +StringCchCatEx( + IN OUT LPTSTR pszDest OPTIONAL, + IN size_t cchDest, + IN LPCTSTR pszSrc OPTIONAL, + OUT LPTSTR* ppszDestEnd OPTIONAL, + OUT size_t* pcchRemaining OPTIONAL, + IN DWORD dwFlags + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'strcat' with + some additional parameters. In addition to functionality provided by + StringCchCat, this routine also returns a pointer to the end of the + destination string and the number of characters left in the destination string + including the null terminator. The flags parameter allows additional controls. + +Arguments: + + pszDest - destination string which must be null terminated + + cchDest - size of destination buffer in characters + length must be (_tcslen(pszDest) + _tcslen(pszSrc) + 1) + to hold all of the combine string plus the null + terminator. + + pszSrc - source string which must be null terminated + + ppszDestEnd - if ppszDestEnd is non-null, the function will return a + pointer to the end of the destination string. If the + function appended any data, the result will point to the + null termination character + + pcchRemaining - if pcchRemaining is non-null, the function will return the + number of characters left in the destination string, + including the null terminator + + dwFlags - controls some details of the string copy: + + STRSAFE_FILL_BEHIND_NULL + if the function succeeds, the low byte of dwFlags will be + used to fill the uninitialize part of destination buffer + behind the null terminator + + STRSAFE_IGNORE_NULLS + treat NULL string pointers like empty strings (TEXT("")). + this flag is useful for emulating functions like lstrcat + + STRSAFE_FILL_ON_FAILURE + if the function fails, the low byte of dwFlags will be + used to fill all of the destination buffer, and it will + be null terminated. This will overwrite any pre-existing + or truncated string + + STRSAFE_NULL_ON_FAILURE + if the function fails, the destination buffer will be set + to the empty string. This will overwrite any pre-existing or + truncated string + + STRSAFE_NO_TRUNCATION + if the function returns STRSAFE_E_INSUFFICIENT_BUFFER, pszDest + will not contain a truncated string, it will remain unchanged. + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag + is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc + may be NULL. An error may still be returned even though NULLS are ignored + due to insufficient space. + +Return Value: + + S_OK - if there was source data and it was all concatenated and + the resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the operation + failed due to insufficient space. When this error + occurs, the destination buffer is modified to contain + a truncated version of the ideal result and is null + terminated. This is useful for situations where + truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCchCatExA(char* pszDest, size_t cchDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFEAPI StringCchCatExW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +#ifdef UNICODE +#define StringCchCatEx StringCchCatExW +#else +#define StringCchCatEx StringCchCatExA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCchCatExA(char* pszDest, size_t cchDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + + // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1 + cbDest = cchDest * sizeof(char); + + hr = StringCatExWorkerA(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, pcchRemaining, dwFlags); + } + + return hr; +} + +STRSAFEAPI StringCchCatExW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + + // safe to multiply cchDest * sizeof(wchar_t) since cchDest < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 + cbDest = cchDest * sizeof(wchar_t); + + hr = StringCatExWorkerW(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, pcchRemaining, dwFlags); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CCH_FUNCTIONS + + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI +StringCbCatEx( + IN OUT LPTSTR pszDest OPTIONAL, + IN size_t cbDest, + IN LPCTSTR pszSrc OPTIONAL, + OUT LPTSTR* ppszDestEnd OPTIONAL, + OUT size_t* pcbRemaining OPTIONAL, + IN DWORD dwFlags + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'strcat' with + some additional parameters. In addition to functionality provided by + StringCbCat, this routine also returns a pointer to the end of the + destination string and the number of bytes left in the destination string + including the null terminator. The flags parameter allows additional controls. + +Arguments: + + pszDest - destination string which must be null terminated + + cbDest - size of destination buffer in bytes. + length must be ((_tcslen(pszDest) + _tcslen(pszSrc) + 1) * sizeof(TCHAR) + to hold all of the combine string plus the null + terminator. + + pszSrc - source string which must be null terminated + + ppszDestEnd - if ppszDestEnd is non-null, the function will return a + pointer to the end of the destination string. If the + function appended any data, the result will point to the + null termination character + + pcbRemaining - if pcbRemaining is non-null, the function will return + the number of bytes left in the destination string, + including the null terminator + + dwFlags - controls some details of the string copy: + + STRSAFE_FILL_BEHIND_NULL + if the function succeeds, the low byte of dwFlags will be + used to fill the uninitialize part of destination buffer + behind the null terminator + + STRSAFE_IGNORE_NULLS + treat NULL string pointers like empty strings (TEXT("")). + this flag is useful for emulating functions like lstrcat + + STRSAFE_FILL_ON_FAILURE + if the function fails, the low byte of dwFlags will be + used to fill all of the destination buffer, and it will + be null terminated. This will overwrite any pre-existing + or truncated string + + STRSAFE_NULL_ON_FAILURE + if the function fails, the destination buffer will be set + to the empty string. This will overwrite any pre-existing or + truncated string + + STRSAFE_NO_TRUNCATION + if the function returns STRSAFE_E_INSUFFICIENT_BUFFER, pszDest + will not contain a truncated string, it will remain unchanged. + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag + is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc + may be NULL. An error may still be returned even though NULLS are ignored + due to insufficient space. + +Return Value: + + S_OK - if there was source data and it was all concatenated + and the resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the operation + failed due to insufficient space. When this error + occurs, the destination buffer is modified to contain + a truncated version of the ideal result and is null + terminated. This is useful for situations where + truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCbCatExA(char* pszDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags); +STRSAFEAPI StringCbCatExW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags); +#ifdef UNICODE +#define StringCbCatEx StringCbCatExW +#else +#define StringCbCatEx StringCbCatExA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCbCatExA(char* pszDest, size_t cbDest, const char* pszSrc, char** 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) + { + // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1 + *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)); + } + } + + return hr; +} + +STRSAFEAPI StringCbCatExW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, wchar_t** 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) + { + // safe to multiply cchRemaining * sizeof(wchar_t) since cchRemaining < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 + *pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)); + } + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CB_FUNCTIONS + + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI +StringCchCatN( + IN OUT LPTSTR pszDest, + IN size_t cchDest, + IN LPCTSTR pszSrc, + IN size_t cchMaxAppend + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'strncat'. + The size of the destination buffer (in characters) is a parameter as well as + the maximum number of characters to append, excluding the null terminator. + This function will not write past the end of the destination buffer and it will + ALWAYS null terminate pszDest (unless it is zero length). + + This function returns a hresult, and not a pointer. It returns + S_OK if all of pszSrc or the first cchMaxAppend characters were appended + to the destination string and it was null terminated, otherwise it will + return a failure code. In failure cases as much of pszSrc will be appended + to pszDest as possible, and pszDest will be null terminated. + +Arguments: + + pszDest - destination string which must be null terminated + + cchDest - size of destination buffer in characters. + length must be (_tcslen(pszDest) + min(cchMaxAppend, _tcslen(pszSrc)) + 1) + to hold all of the combine string plus the null + terminator. + + pszSrc - source string + + cchMaxAppend - maximum number of characters to append + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL. See StringCchCatNEx if you require + the handling of NULL values. + +Return Value: + + S_OK - if all of pszSrc or the first cchMaxAppend characters + were concatenated to pszDest and the resultant dest + string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the operation + failed due to insufficient space. When this error + occurs, the destination buffer is modified to contain + a truncated version of the ideal result and is null + terminated. This is useful for situations where + truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCchCatNA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend); +STRSAFEAPI StringCchCatNW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchMaxAppend); +#ifdef UNICODE +#define StringCchCatN StringCchCatNW +#else +#define StringCchCatN StringCchCatNA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCchCatNA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCatNWorkerA(pszDest, cchDest, pszSrc, cchMaxAppend); + } + + return hr; +} + +STRSAFEAPI StringCchCatNW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchMaxAppend) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCatNWorkerW(pszDest, cchDest, pszSrc, cchMaxAppend); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CCH_FUNCTIONS + + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI +StringCbCatN( + IN OUT LPTSTR pszDest, + IN size_t cbDest, + IN LPCTSTR pszSrc, + IN size_t cbMaxAppend + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'strncat'. + The size of the destination buffer (in bytes) is a parameter as well as + the maximum number of bytes to append, excluding the null terminator. + This function will not write past the end of the destination buffer and it will + ALWAYS null terminate pszDest (unless it is zero length). + + This function returns a hresult, and not a pointer. It returns + S_OK if all of pszSrc or the first cbMaxAppend bytes were appended + to the destination string and it was null terminated, otherwise it will + return a failure code. In failure cases as much of pszSrc will be appended + to pszDest as possible, and pszDest will be null terminated. + +Arguments: + + pszDest - destination string which must be null terminated + + cbDest - size of destination buffer in bytes. + length must be ((_tcslen(pszDest) + min(cbMaxAppend / sizeof(TCHAR), _tcslen(pszSrc)) + 1) * sizeof(TCHAR) + to hold all of the combine string plus the null + terminator. + + pszSrc - source string + + cbMaxAppend - maximum number of bytes to append + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL. See StringCbCatNEx if you require + the handling of NULL values. + +Return Value: + + S_OK - if all of pszSrc or the first cbMaxAppend bytes were + concatenated to pszDest and the resultant dest string + was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the operation + failed due to insufficient space. When this error + occurs, the destination buffer is modified to contain + a truncated version of the ideal result and is null + terminated. This is useful for situations where + truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCbCatNA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbMaxAppend); +STRSAFEAPI StringCbCatNW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, size_t cbMaxAppend); +#ifdef UNICODE +#define StringCbCatN StringCbCatNW +#else +#define StringCbCatN StringCbCatNA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCbCatNA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbMaxAppend) +{ + HRESULT hr; + size_t cchDest; + + cchDest = cbDest / sizeof(char); + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cchMaxAppend; + + cchMaxAppend = cbMaxAppend / sizeof(char); + + hr = StringCatNWorkerA(pszDest, cchDest, pszSrc, cchMaxAppend); + } + + return hr; +} + +STRSAFEAPI StringCbCatNW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, size_t cbMaxAppend) +{ + HRESULT hr; + size_t cchDest; + + cchDest = cbDest / sizeof(wchar_t); + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cchMaxAppend; + + cchMaxAppend = cbMaxAppend / sizeof(wchar_t); + + hr = StringCatNWorkerW(pszDest, cchDest, pszSrc, cchMaxAppend); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CB_FUNCTIONS + + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI +StringCchCatNEx( + IN OUT LPTSTR pszDest OPTIONAL, + IN size_t cchDest, + IN LPCTSTR pszSrc OPTIONAL, + IN size_t cchMaxAppend, + OUT LPTSTR* ppszDestEnd OPTIONAL, + OUT size_t* pcchRemaining OPTIONAL, + IN DWORD dwFlags + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'strncat', with + some additional parameters. In addition to functionality provided by + StringCchCatN, this routine also returns a pointer to the end of the + destination string and the number of characters left in the destination string + including the null terminator. The flags parameter allows additional controls. + +Arguments: + + pszDest - destination string which must be null terminated + + cchDest - size of destination buffer in characters. + length must be (_tcslen(pszDest) + min(cchMaxAppend, _tcslen(pszSrc)) + 1) + to hold all of the combine string plus the null + terminator. + + pszSrc - source string + + cchMaxAppend - maximum number of characters to append + + ppszDestEnd - if ppszDestEnd is non-null, the function will return a + pointer to the end of the destination string. If the + function appended any data, the result will point to the + null termination character + + pcchRemaining - if pcchRemaining is non-null, the function will return the + number of characters left in the destination string, + including the null terminator + + dwFlags - controls some details of the string copy: + + STRSAFE_FILL_BEHIND_NULL + if the function succeeds, the low byte of dwFlags will be + used to fill the uninitialize part of destination buffer + behind the null terminator + + STRSAFE_IGNORE_NULLS + treat NULL string pointers like empty strings (TEXT("")) + + STRSAFE_FILL_ON_FAILURE + if the function fails, the low byte of dwFlags will be + used to fill all of the destination buffer, and it will + be null terminated. This will overwrite any pre-existing + or truncated string + + STRSAFE_NULL_ON_FAILURE + if the function fails, the destination buffer will be set + to the empty string. This will overwrite any pre-existing or + truncated string + + STRSAFE_NO_TRUNCATION + if the function returns STRSAFE_E_INSUFFICIENT_BUFFER, pszDest + will not contain a truncated string, it will remain unchanged. + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag + is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc + may be NULL. An error may still be returned even though NULLS are ignored + due to insufficient space. + +Return Value: + + S_OK - if all of pszSrc or the first cchMaxAppend characters + were concatenated to pszDest and the resultant dest + string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the operation + failed due to insufficient space. When this error + occurs, the destination buffer is modified to contain + a truncated version of the ideal result and is null + terminated. This is useful for situations where + truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCchCatNExA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFEAPI StringCchCatNExW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchMaxAppend, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +#ifdef UNICODE +#define StringCchCatNEx StringCchCatNExW +#else +#define StringCchCatNEx StringCchCatNExA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCchCatNExA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + + // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1 + cbDest = cchDest * sizeof(char); + + hr = StringCatNExWorkerA(pszDest, cchDest, cbDest, pszSrc, cchMaxAppend, ppszDestEnd, pcchRemaining, dwFlags); + } + + return hr; +} + +STRSAFEAPI StringCchCatNExW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchMaxAppend, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + + // safe to multiply cchDest * sizeof(wchar_t) since cchDest < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 + cbDest = cchDest * sizeof(wchar_t); + + hr = StringCatNExWorkerW(pszDest, cchDest, cbDest, pszSrc, cchMaxAppend, ppszDestEnd, pcchRemaining, dwFlags); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CCH_FUNCTIONS + + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI +StringCbCatNEx( + IN OUT LPTSTR pszDest OPTIONAL, + IN size_t cbDest, + IN LPCTSTR pszSrc OPTIONAL, + IN size_t cbMaxAppend, + OUT LPTSTR* ppszDestEnd OPTIONAL, + OUT size_t* pcchRemaining OPTIONAL, + IN DWORD dwFlags + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'strncat', with + some additional parameters. In addition to functionality provided by + StringCbCatN, this routine also returns a pointer to the end of the + destination string and the number of bytes left in the destination string + including the null terminator. The flags parameter allows additional controls. + +Arguments: + + pszDest - destination string which must be null terminated + + cbDest - size of destination buffer in bytes. + length must be ((_tcslen(pszDest) + min(cbMaxAppend / sizeof(TCHAR), _tcslen(pszSrc)) + 1) * sizeof(TCHAR) + to hold all of the combine string plus the null + terminator. + + pszSrc - source string + + cbMaxAppend - maximum number of bytes to append + + ppszDestEnd - if ppszDestEnd is non-null, the function will return a + pointer to the end of the destination string. If the + function appended any data, the result will point to the + null termination character + + pcbRemaining - if pcbRemaining is non-null, the function will return the + number of bytes left in the destination string, + including the null terminator + + dwFlags - controls some details of the string copy: + + STRSAFE_FILL_BEHIND_NULL + if the function succeeds, the low byte of dwFlags will be + used to fill the uninitialize part of destination buffer + behind the null terminator + + STRSAFE_IGNORE_NULLS + treat NULL string pointers like empty strings (TEXT("")) + + STRSAFE_FILL_ON_FAILURE + if the function fails, the low byte of dwFlags will be + used to fill all of the destination buffer, and it will + be null terminated. This will overwrite any pre-existing + or truncated string + + STRSAFE_NULL_ON_FAILURE + if the function fails, the destination buffer will be set + to the empty string. This will overwrite any pre-existing or + truncated string + + STRSAFE_NO_TRUNCATION + if the function returns STRSAFE_E_INSUFFICIENT_BUFFER, pszDest + will not contain a truncated string, it will remain unchanged. + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag + is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc + may be NULL. An error may still be returned even though NULLS are ignored + due to insufficient space. + +Return Value: + + S_OK - if all of pszSrc or the first cbMaxAppend bytes were + concatenated to pszDest and the resultant dest string + was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the operation + failed due to insufficient space. When this error + occurs, the destination buffer is modified to contain + a truncated version of the ideal result and is null + terminated. This is useful for situations where + truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCbCatNExA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbMaxAppend, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags); +STRSAFEAPI StringCbCatNExW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, size_t cbMaxAppend, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags); +#ifdef UNICODE +#define StringCbCatNEx StringCbCatNExW +#else +#define StringCbCatNEx StringCbCatNExA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCbCatNExA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbMaxAppend, char** 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 + { + size_t cchMaxAppend; + + cchMaxAppend = cbMaxAppend / sizeof(char); + + hr = StringCatNExWorkerA(pszDest, cchDest, cbDest, pszSrc, cchMaxAppend, ppszDestEnd, &cchRemaining, dwFlags); + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (pcbRemaining) + { + // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1 + *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)); + } + } + + return hr; +} + +STRSAFEAPI StringCbCatNExW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszSrc, size_t cbMaxAppend, wchar_t** 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 + { + size_t cchMaxAppend; + + cchMaxAppend = cbMaxAppend / sizeof(wchar_t); + + hr = StringCatNExWorkerW(pszDest, cchDest, cbDest, pszSrc, cchMaxAppend, ppszDestEnd, &cchRemaining, dwFlags); + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (pcbRemaining) + { + // safe to multiply cchRemaining * sizeof(wchar_t) since cchRemaining < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 + *pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)); + } + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CB_FUNCTIONS + + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI +StringCchVPrintf( + OUT LPTSTR pszDest, + IN size_t cchDest, + IN LPCTSTR pszFormat, + IN va_list argList + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'vsprintf'. + The size of the destination buffer (in characters) is a parameter and + this function will not write past the end of this buffer and it will + ALWAYS null terminate the destination buffer (unless it is zero length). + + This function returns a hresult, and not a pointer. It returns + S_OK if the string was printed without truncation and null terminated, + otherwise it will return a failure code. In failure cases it will return + a truncated version of the ideal result. + +Arguments: + + pszDest - destination string + + cchDest - size of destination buffer in characters + length must be sufficient to hold the resulting formatted + string, including the null terminator. + + pszFormat - format string which must be null terminated + + argList - va_list from the variable arguments according to the + stdarg.h convention + +Notes: + Behavior is undefined if destination, format strings or any arguments + strings overlap. + + pszDest and pszFormat should not be NULL. See StringCchVPrintfEx if you + require the handling of NULL values. + +Return Value: + + S_OK - if there was sufficient space in the dest buffer for + the resultant string and it was null terminated. + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the print + operation failed due to insufficient space. When this + error occurs, the destination buffer is modified to + contain a truncated version of the ideal result and is + null terminated. This is useful for situations where + truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCchVPrintfA(char* pszDest, size_t cchDest, const char* pszFormat, va_list argList); +STRSAFEAPI StringCchVPrintfW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszFormat, va_list argList); +#ifdef UNICODE +#define StringCchVPrintf StringCchVPrintfW +#else +#define StringCchVPrintf StringCchVPrintfA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCchVPrintfA(char* pszDest, size_t cchDest, const char* 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(wchar_t* pszDest, size_t cchDest, const wchar_t* 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 // STRSAFE_INLINE +#endif // !STRSAFE_NO_CCH_FUNCTIONS + + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI +StringCbVPrintf( + OUT LPTSTR pszDest, + IN size_t cbDest, + IN LPCTSTR pszFormat, + IN va_list argList + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'vsprintf'. + The size of the destination buffer (in bytes) is a parameter and + this function will not write past the end of this buffer and it will + ALWAYS null terminate the destination buffer (unless it is zero length). + + This function returns a hresult, and not a pointer. It returns + S_OK if the string was printed without truncation and null terminated, + otherwise it will return a failure code. In failure cases it will return + a truncated version of the ideal result. + +Arguments: + + pszDest - destination string + + cbDest - size of destination buffer in bytes + length must be sufficient to hold the resulting formatted + string, including the null terminator. + + pszFormat - format string which must be null terminated + + argList - va_list from the variable arguments according to the + stdarg.h convention + +Notes: + Behavior is undefined if destination, format strings or any arguments + strings overlap. + + pszDest and pszFormat should not be NULL. See StringCbVPrintfEx if you + require the handling of NULL values. + + +Return Value: + + S_OK - if there was sufficient space in the dest buffer for + the resultant string and it was null terminated. + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the print + operation failed due to insufficient space. When this + error occurs, the destination buffer is modified to + contain a truncated version of the ideal result and is + null terminated. This is useful for situations where + truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCbVPrintfA(char* pszDest, size_t cbDest, const char* pszFormat, va_list argList); +STRSAFEAPI StringCbVPrintfW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszFormat, va_list argList); +#ifdef UNICODE +#define StringCbVPrintf StringCbVPrintfW +#else +#define StringCbVPrintf StringCbVPrintfA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCbVPrintfA(char* pszDest, size_t cbDest, const char* 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(wchar_t* pszDest, size_t cbDest, const wchar_t* 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 // STRSAFE_INLINE +#endif // !STRSAFE_NO_CB_FUNCTIONS + + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI +StringCchPrintf( + OUT LPTSTR pszDest, + IN size_t cchDest, + IN LPCTSTR pszFormat, + ... + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'sprintf'. + The size of the destination buffer (in characters) is a parameter and + this function will not write past the end of this buffer and it will + ALWAYS null terminate the destination buffer (unless it is zero length). + + This function returns a hresult, and not a pointer. It returns + S_OK if the string was printed without truncation and null terminated, + otherwise it will return a failure code. In failure cases it will return + a truncated version of the ideal result. + +Arguments: + + pszDest - destination string + + cchDest - size of destination buffer in characters + length must be sufficient to hold the resulting formatted + string, including the null terminator. + + pszFormat - format string which must be null terminated + + ... - additional parameters to be formatted according to + the format string + +Notes: + Behavior is undefined if destination, format strings or any arguments + strings overlap. + + pszDest and pszFormat should not be NULL. See StringCchPrintfEx if you + require the handling of NULL values. + +Return Value: + + S_OK - if there was sufficient space in the dest buffer for + the resultant string and it was null terminated. + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the print + operation failed due to insufficient space. When this + error occurs, the destination buffer is modified to + contain a truncated version of the ideal result and is + null terminated. This is useful for situations where + truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCchPrintfA(char* pszDest, size_t cchDest, const char* pszFormat, ...); +STRSAFEAPI StringCchPrintfW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszFormat, ...); +#ifdef UNICODE +#define StringCchPrintf StringCchPrintfW +#else +#define StringCchPrintf StringCchPrintfA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCchPrintfA(char* pszDest, size_t cchDest, const char* 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(wchar_t* pszDest, size_t cchDest, const wchar_t* 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 // STRSAFE_INLINE +#endif // !STRSAFE_NO_CCH_FUNCTIONS + + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI +StringCbPrintf( + OUT LPTSTR pszDest, + IN size_t cbDest, + IN LPCTSTR pszFormat, + ... + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'sprintf'. + The size of the destination buffer (in bytes) is a parameter and + this function will not write past the end of this buffer and it will + ALWAYS null terminate the destination buffer (unless it is zero length). + + This function returns a hresult, and not a pointer. It returns + S_OK if the string was printed without truncation and null terminated, + otherwise it will return a failure code. In failure cases it will return + a truncated version of the ideal result. + +Arguments: + + pszDest - destination string + + cbDest - size of destination buffer in bytes + length must be sufficient to hold the resulting formatted + string, including the null terminator. + + pszFormat - format string which must be null terminated + + ... - additional parameters to be formatted according to + the format string + +Notes: + Behavior is undefined if destination, format strings or any arguments + strings overlap. + + pszDest and pszFormat should not be NULL. See StringCbPrintfEx if you + require the handling of NULL values. + + +Return Value: + + S_OK - if there was sufficient space in the dest buffer for + the resultant string and it was null terminated. + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the print + operation failed due to insufficient space. When this + error occurs, the destination buffer is modified to + contain a truncated version of the ideal result and is + null terminated. This is useful for situations where + truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCbPrintfA(char* pszDest, size_t cbDest, const char* pszFormat, ...); +STRSAFEAPI StringCbPrintfW(wchar_t* pszDest, size_t cbDest, const wchar_t* pszFormat, ...); +#ifdef UNICODE +#define StringCbPrintf StringCbPrintfW +#else +#define StringCbPrintf StringCbPrintfA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCbPrintfA(char* pszDest, size_t cbDest, const char* 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(wchar_t* pszDest, size_t cbDest, const wchar_t* 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 // STRSAFE_INLINE +#endif // !STRSAFE_NO_CB_FUNCTIONS + + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI +StringCchPrintfEx( + OUT LPTSTR pszDest OPTIONAL, + IN size_t cchDest, + OUT LPTSTR* ppszDestEnd OPTIONAL, + OUT size_t* pcchRemaining OPTIONAL, + IN DWORD dwFlags, + IN LPCTSTR pszFormat OPTIONAL, + ... + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'sprintf' with + some additional parameters. In addition to functionality provided by + StringCchPrintf, this routine also returns a pointer to the end of the + destination string and the number of characters left in the destination string + including the null terminator. The flags parameter allows additional controls. + +Arguments: + + pszDest - destination string + + cchDest - size of destination buffer in characters. + length must be sufficient to contain the resulting + formatted string plus the null terminator. + + ppszDestEnd - if ppszDestEnd is non-null, the function will return a + pointer to the end of the destination string. If the + function printed any data, the result will point to the + null termination character + + pcchRemaining - if pcchRemaining is non-null, the function will return + the number of characters left in the destination string, + including the null terminator + + dwFlags - controls some details of the string copy: + + STRSAFE_FILL_BEHIND_NULL + if the function succeeds, the low byte of dwFlags will be + used to fill the uninitialize part of destination buffer + behind the null terminator + + STRSAFE_IGNORE_NULLS + treat NULL string pointers like empty strings (TEXT("")) + + STRSAFE_FILL_ON_FAILURE + if the function fails, the low byte of dwFlags will be + used to fill all of the destination buffer, and it will + be null terminated. This will overwrite any truncated + string returned when the failure is + STRSAFE_E_INSUFFICIENT_BUFFER + + STRSAFE_NO_TRUNCATION / + STRSAFE_NULL_ON_FAILURE + if the function fails, the destination buffer will be set + to the empty string. This will overwrite any truncated string + returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER. + + pszFormat - format string which must be null terminated + + ... - additional parameters to be formatted according to + the format string + +Notes: + Behavior is undefined if destination, format strings or any arguments + strings overlap. + + pszDest and pszFormat should not be NULL unless the STRSAFE_IGNORE_NULLS + flag is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and + pszFormat may be NULL. An error may still be returned even though NULLS + are ignored due to insufficient space. + +Return Value: + + S_OK - if there was source data and it was all concatenated and + the resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the print + operation failed due to insufficient space. When this + error occurs, the destination buffer is modified to + contain a truncated version of the ideal result and is + null terminated. This is useful for situations where + truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCchPrintfExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, ...); +STRSAFEAPI StringCchPrintfExW(wchar_t* pszDest, size_t cchDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const wchar_t* pszFormat, ...); +#ifdef UNICODE +#define StringCchPrintfEx StringCchPrintfExW +#else +#define StringCchPrintfEx StringCchPrintfExA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCchPrintfExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, ...) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + va_list argList; + + // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1 + 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(wchar_t* pszDest, size_t cchDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const wchar_t* pszFormat, ...) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + va_list argList; + + // safe to multiply cchDest * sizeof(wchar_t) since cchDest < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 + 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 // STRSAFE_INLINE +#endif // !STRSAFE_NO_CCH_FUNCTIONS + + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI +StringCbPrintfEx( + OUT LPTSTR pszDest OPTIONAL, + IN size_t cbDest, + OUT LPTSTR* ppszDestEnd OPTIONAL, + OUT size_t* pcbRemaining OPTIONAL, + IN DWORD dwFlags, + IN LPCTSTR pszFormat OPTIONAL, + ... + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'sprintf' with + some additional parameters. In addition to functionality provided by + StringCbPrintf, this routine also returns a pointer to the end of the + destination string and the number of bytes left in the destination string + including the null terminator. The flags parameter allows additional controls. + +Arguments: + + pszDest - destination string + + cbDest - size of destination buffer in bytes. + length must be sufficient to contain the resulting + formatted string plus the null terminator. + + ppszDestEnd - if ppszDestEnd is non-null, the function will return a + pointer to the end of the destination string. If the + function printed any data, the result will point to the + null termination character + + pcbRemaining - if pcbRemaining is non-null, the function will return + the number of bytes left in the destination string, + including the null terminator + + dwFlags - controls some details of the string copy: + + STRSAFE_FILL_BEHIND_NULL + if the function succeeds, the low byte of dwFlags will be + used to fill the uninitialize part of destination buffer + behind the null terminator + + STRSAFE_IGNORE_NULLS + treat NULL string pointers like empty strings (TEXT("")) + + STRSAFE_FILL_ON_FAILURE + if the function fails, the low byte of dwFlags will be + used to fill all of the destination buffer, and it will + be null terminated. This will overwrite any truncated + string returned when the failure is + STRSAFE_E_INSUFFICIENT_BUFFER + + STRSAFE_NO_TRUNCATION / + STRSAFE_NULL_ON_FAILURE + if the function fails, the destination buffer will be set + to the empty string. This will overwrite any truncated string + returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER. + + pszFormat - format string which must be null terminated + + ... - additional parameters to be formatted according to + the format string + +Notes: + Behavior is undefined if destination, format strings or any arguments + strings overlap. + + pszDest and pszFormat should not be NULL unless the STRSAFE_IGNORE_NULLS + flag is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and + pszFormat may be NULL. An error may still be returned even though NULLS + are ignored due to insufficient space. + +Return Value: + + S_OK - if there was source data and it was all concatenated and + the resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the print + operation failed due to insufficient space. When this + error occurs, the destination buffer is modified to + contain a truncated version of the ideal result and is + null terminated. This is useful for situations where + truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCbPrintfExA(char* pszDest, size_t cbDest, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const char* pszFormat, ...); +STRSAFEAPI StringCbPrintfExW(wchar_t* pszDest, size_t cbDest, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const wchar_t* pszFormat, ...); +#ifdef UNICODE +#define StringCbPrintfEx StringCbPrintfExW +#else +#define StringCbPrintfEx StringCbPrintfExA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCbPrintfExA(char* pszDest, size_t cbDest, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const char* 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) + { + // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1 + *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)); + } + } + + return hr; +} + +STRSAFEAPI StringCbPrintfExW(wchar_t* pszDest, size_t cbDest, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const wchar_t* 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) + { + // safe to multiply cchRemaining * sizeof(wchar_t) since cchRemaining < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 + *pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)); + } + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CB_FUNCTIONS + + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI +StringCchVPrintfEx( + OUT LPTSTR pszDest OPTIONAL, + IN size_t cchDest, + OUT LPTSTR* ppszDestEnd OPTIONAL, + OUT size_t* pcchRemaining OPTIONAL, + IN DWORD dwFlags, + IN LPCTSTR pszFormat OPTIONAL, + IN va_list argList + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'vsprintf' with + some additional parameters. In addition to functionality provided by + StringCchVPrintf, this routine also returns a pointer to the end of the + destination string and the number of characters left in the destination string + including the null terminator. The flags parameter allows additional controls. + +Arguments: + + pszDest - destination string + + cchDest - size of destination buffer in characters. + length must be sufficient to contain the resulting + formatted string plus the null terminator. + + ppszDestEnd - if ppszDestEnd is non-null, the function will return a + pointer to the end of the destination string. If the + function printed any data, the result will point to the + null termination character + + pcchRemaining - if pcchRemaining is non-null, the function will return + the number of characters left in the destination string, + including the null terminator + + dwFlags - controls some details of the string copy: + + STRSAFE_FILL_BEHIND_NULL + if the function succeeds, the low byte of dwFlags will be + used to fill the uninitialize part of destination buffer + behind the null terminator + + STRSAFE_IGNORE_NULLS + treat NULL string pointers like empty strings (TEXT("")) + + STRSAFE_FILL_ON_FAILURE + if the function fails, the low byte of dwFlags will be + used to fill all of the destination buffer, and it will + be null terminated. This will overwrite any truncated + string returned when the failure is + STRSAFE_E_INSUFFICIENT_BUFFER + + STRSAFE_NO_TRUNCATION / + STRSAFE_NULL_ON_FAILURE + if the function fails, the destination buffer will be set + to the empty string. This will overwrite any truncated string + returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER. + + pszFormat - format string which must be null terminated + + argList - va_list from the variable arguments according to the + stdarg.h convention + +Notes: + Behavior is undefined if destination, format strings or any arguments + strings overlap. + + pszDest and pszFormat should not be NULL unless the STRSAFE_IGNORE_NULLS + flag is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and + pszFormat may be NULL. An error may still be returned even though NULLS + are ignored due to insufficient space. + +Return Value: + + S_OK - if there was source data and it was all concatenated and + the resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the print + operation failed due to insufficient space. When this + error occurs, the destination buffer is modified to + contain a truncated version of the ideal result and is + null terminated. This is useful for situations where + truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCchVPrintfExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList); +STRSAFEAPI StringCchVPrintfExW(wchar_t* pszDest, size_t cchDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const wchar_t* pszFormat, va_list argList); +#ifdef UNICODE +#define StringCchVPrintfEx StringCchVPrintfExW +#else +#define StringCchVPrintfEx StringCchVPrintfExA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCchVPrintfExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + + // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1 + cbDest = cchDest * sizeof(char); + + hr = StringVPrintfExWorkerA(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags, pszFormat, argList); + } + + return hr; +} + +STRSAFEAPI StringCchVPrintfExW(wchar_t* pszDest, size_t cchDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const wchar_t* pszFormat, va_list argList) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + + // safe to multiply cchDest * sizeof(wchar_t) since cchDest < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 + cbDest = cchDest * sizeof(wchar_t); + + hr = StringVPrintfExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags, pszFormat, argList); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CCH_FUNCTIONS + + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI +StringCbVPrintfEx( + OUT LPTSTR pszDest OPTIONAL, + IN size_t cbDest, + OUT LPTSTR* ppszDestEnd OPTIONAL, + OUT size_t* pcbRemaining OPTIONAL, + IN DWORD dwFlags, + IN LPCTSTR pszFormat OPTIONAL, + IN va_list argList + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'vsprintf' with + some additional parameters. In addition to functionality provided by + StringCbVPrintf, this routine also returns a pointer to the end of the + destination string and the number of characters left in the destination string + including the null terminator. The flags parameter allows additional controls. + +Arguments: + + pszDest - destination string + + cbDest - size of destination buffer in bytes. + length must be sufficient to contain the resulting + formatted string plus the null terminator. + + ppszDestEnd - if ppszDestEnd is non-null, the function will return + a pointer to the end of the destination string. If the + function printed any data, the result will point to the + null termination character + + pcbRemaining - if pcbRemaining is non-null, the function will return + the number of bytes left in the destination string, + including the null terminator + + dwFlags - controls some details of the string copy: + + STRSAFE_FILL_BEHIND_NULL + if the function succeeds, the low byte of dwFlags will be + used to fill the uninitialize part of destination buffer + behind the null terminator + + STRSAFE_IGNORE_NULLS + treat NULL string pointers like empty strings (TEXT("")) + + STRSAFE_FILL_ON_FAILURE + if the function fails, the low byte of dwFlags will be + used to fill all of the destination buffer, and it will + be null terminated. This will overwrite any truncated + string returned when the failure is + STRSAFE_E_INSUFFICIENT_BUFFER + + STRSAFE_NO_TRUNCATION / + STRSAFE_NULL_ON_FAILURE + if the function fails, the destination buffer will be set + to the empty string. This will overwrite any truncated string + returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER. + + pszFormat - format string which must be null terminated + + argList - va_list from the variable arguments according to the + stdarg.h convention + +Notes: + Behavior is undefined if destination, format strings or any arguments + strings overlap. + + pszDest and pszFormat should not be NULL unless the STRSAFE_IGNORE_NULLS + flag is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and + pszFormat may be NULL. An error may still be returned even though NULLS + are ignored due to insufficient space. + +Return Value: + + S_OK - if there was source data and it was all concatenated and + the resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the print + operation failed due to insufficient space. When this + error occurs, the destination buffer is modified to + contain a truncated version of the ideal result and is + null terminated. This is useful for situations where + truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCbVPrintfExA(char* pszDest, size_t cbDest, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList); +STRSAFEAPI StringCbVPrintfExW(wchar_t* pszDest, size_t cbDest, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const wchar_t* pszFormat, va_list argList); +#ifdef UNICODE +#define StringCbVPrintfEx StringCbVPrintfExW +#else +#define StringCbVPrintfEx StringCbVPrintfExA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCbVPrintfExA(char* pszDest, size_t cbDest, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const char* 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) + { + // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1 + *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)); + } + } + + return hr; +} + +STRSAFEAPI StringCbVPrintfExW(wchar_t* pszDest, size_t cbDest, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags, const wchar_t* 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) + { + // safe to multiply cchRemaining * sizeof(wchar_t) since cchRemaining < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 + *pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)); + } + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CB_FUNCTIONS + + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI +StringCchGets( + OUT LPTSTR pszDest, + IN size_t cchDest + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'gets'. + The size of the destination buffer (in characters) is a parameter and + this function will not write past the end of this buffer and it will + ALWAYS null terminate the destination buffer (unless it is zero length). + + This routine is not a replacement for fgets. That function does not replace + newline characters with a null terminator. + + This function returns a hresult, and not a pointer. It returns + S_OK if any characters were read from stdin and copied to pszDest and + pszDest was null terminated, otherwise it will return a failure code. + +Arguments: + + pszDest - destination string + + cchDest - size of destination buffer in characters. + +Notes: + pszDest should not be NULL. See StringCchGetsEx if you require the handling + of NULL values. + + cchDest must be > 1 for this function to succeed. + +Return Value: + + S_OK - data was read from stdin and copied, and the resultant + dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_END_OF_FILE / + HRESULT_CODE(hr) == ERROR_HANDLE_EOF + - this return value indicates an error or end-of-file + condition, use feof or ferror to determine which one has + occured. + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that there was + insufficient space in the destination buffer to copy any + data + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function. + +--*/ + +#ifndef STRSAFE_LIB_IMPL +STRSAFE_INLINE_API StringCchGetsA(char* pszDest, size_t cchDest); +STRSAFE_INLINE_API StringCchGetsW(wchar_t* pszDest, size_t cchDest); +#ifdef UNICODE +#define StringCchGets StringCchGetsW +#else +#define StringCchGets StringCchGetsA +#endif // !UNICODE + +STRSAFE_INLINE_API StringCchGetsA(char* pszDest, size_t cchDest) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + + // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1 + cbDest = cchDest * sizeof(char); + + hr = StringGetsExWorkerA(pszDest, cchDest, cbDest, NULL, NULL, 0); + } + + return hr; +} + +STRSAFE_INLINE_API StringCchGetsW(wchar_t* pszDest, size_t cchDest) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + + // safe to multiply cchDest * sizeof(wchar_t) since cchDest < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 + cbDest = cchDest * sizeof(wchar_t); + + hr = StringGetsExWorkerW(pszDest, cchDest, cbDest, NULL, NULL, 0); + } + + return hr; +} +#endif // !STRSAFE_NO_CCH_FUNCTIONS +#endif // !STRSAFE_LIB_IMPL + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI +StringCbGets( + OUT LPTSTR pszDest, + IN size_t cbDest + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'gets'. + The size of the destination buffer (in bytes) is a parameter and + this function will not write past the end of this buffer and it will + ALWAYS null terminate the destination buffer (unless it is zero length). + + This routine is not a replacement for fgets. That function does not replace + newline characters with a null terminator. + + This function returns a hresult, and not a pointer. It returns + S_OK if any characters were read from stdin and copied to pszDest + and pszDest was null terminated, otherwise it will return a failure code. + +Arguments: + + pszDest - destination string + + cbDest - size of destination buffer in bytes. + +Notes: + pszDest should not be NULL. See StringCbGetsEx if you require the handling + of NULL values. + + cbDest must be > sizeof(TCHAR) for this function to succeed. + +Return Value: + + S_OK - data was read from stdin and copied, and the resultant + dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_END_OF_FILE / + HRESULT_CODE(hr) == ERROR_HANDLE_EOF + - this return value indicates an error or end-of-file + condition, use feof or ferror to determine which one has + occured. + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that there was + insufficient space in the destination buffer to copy any + data + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function. + +--*/ + +#ifndef STRSAFE_LIB_IMPL +STRSAFE_INLINE_API StringCbGetsA(char* pszDest, size_t cbDest); +STRSAFE_INLINE_API StringCbGetsW(wchar_t* pszDest, size_t cbDest); +#ifdef UNICODE +#define StringCbGets StringCbGetsW +#else +#define StringCbGets StringCbGetsA +#endif // !UNICODE + +STRSAFE_INLINE_API StringCbGetsA(char* pszDest, size_t cbDest) +{ + HRESULT hr; + size_t cchDest; + + // convert to count of characters + 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(wchar_t* pszDest, size_t cbDest) +{ + HRESULT hr; + size_t cchDest; + + // convert to count of characters + 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 // !STRSAFE_NO_CB_FUNCTIONS +#endif // !STRSAFE_LIB_IMPL + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI +StringCchGetsEx( + OUT LPTSTR pszDest OPTIONAL, + IN size_t cchDest, + OUT LPTSTR* ppszDestEnd OPTIONAL, + OUT size_t* pcchRemaining OPTIONAL, + IN DWORD dwFlags + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'gets' with + some additional parameters. In addition to functionality provided by + StringCchGets, this routine also returns a pointer to the end of the + destination string and the number of characters left in the destination string + including the null terminator. The flags parameter allows additional controls. + +Arguments: + + pszDest - destination string + + cchDest - size of destination buffer in characters. + + ppszDestEnd - if ppszDestEnd is non-null, the function will return a + pointer to the end of the destination string. If the + function copied any data, the result will point to the + null termination character + + pcchRemaining - if pcchRemaining is non-null, the function will return the + number of characters left in the destination string, + including the null terminator + + dwFlags - controls some details of the string copy: + + STRSAFE_FILL_BEHIND_NULL + if the function succeeds, the low byte of dwFlags will be + used to fill the uninitialize part of destination buffer + behind the null terminator + + STRSAFE_IGNORE_NULLS + treat NULL string pointers like empty strings (TEXT("")). + + STRSAFE_FILL_ON_FAILURE + if the function fails, the low byte of dwFlags will be + used to fill all of the destination buffer, and it will + be null terminated. + + STRSAFE_NO_TRUNCATION / + STRSAFE_NULL_ON_FAILURE + if the function fails, the destination buffer will be set + to the empty string. + +Notes: + pszDest should not be NULL unless the STRSAFE_IGNORE_NULLS flag is specified. + If STRSAFE_IGNORE_NULLS is passed and pszDest is NULL, an error may still be + returned even though NULLS are ignored + + cchDest must be > 1 for this function to succeed. + +Return Value: + + S_OK - data was read from stdin and copied, and the resultant + dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_END_OF_FILE / + HRESULT_CODE(hr) == ERROR_HANDLE_EOF + - this return value indicates an error or end-of-file + condition, use feof or ferror to determine which one has + occured. + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that there was + insufficient space in the destination buffer to copy any + data + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function. + +--*/ + +#ifndef STRSAFE_LIB_IMPL +STRSAFE_INLINE_API StringCchGetsExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFE_INLINE_API StringCchGetsExW(wchar_t* pszDest, size_t cchDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +#ifdef UNICODE +#define StringCchGetsEx StringCchGetsExW +#else +#define StringCchGetsEx StringCchGetsExA +#endif // !UNICODE + +STRSAFE_INLINE_API StringCchGetsExA(char* pszDest, size_t cchDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + + // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1 + cbDest = cchDest * sizeof(char); + + hr = StringGetsExWorkerA(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags); + } + + return hr; +} + +STRSAFE_INLINE_API StringCchGetsExW(wchar_t* pszDest, size_t cchDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + + // safe to multiply cchDest * sizeof(wchar_t) since cchDest < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 + cbDest = cchDest * sizeof(wchar_t); + + hr = StringGetsExWorkerW(pszDest, cchDest, cbDest, ppszDestEnd, pcchRemaining, dwFlags); + } + + return hr; +} +#endif // !STRSAFE_NO_CCH_FUNCTIONS +#endif // !STRSAFE_LIB_IMPL + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI +StringCbGetsEx( + OUT LPTSTR pszDest OPTIONAL, + IN size_t cbDest, + OUT LPTSTR* ppszDestEnd OPTIONAL, + OUT size_t* pcbRemaining OPTIONAL, + IN DWORD dwFlags + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'gets' with + some additional parameters. In addition to functionality provided by + StringCbGets, this routine also returns a pointer to the end of the + destination string and the number of characters left in the destination string + including the null terminator. The flags parameter allows additional controls. + +Arguments: + + pszDest - destination string + + cbDest - size of destination buffer in bytes. + + ppszDestEnd - if ppszDestEnd is non-null, the function will return a + pointer to the end of the destination string. If the + function copied any data, the result will point to the + null termination character + + pcbRemaining - if pbRemaining is non-null, the function will return the + number of bytes left in the destination string, + including the null terminator + + dwFlags - controls some details of the string copy: + + STRSAFE_FILL_BEHIND_NULL + if the function succeeds, the low byte of dwFlags will be + used to fill the uninitialize part of destination buffer + behind the null terminator + + STRSAFE_IGNORE_NULLS + treat NULL string pointers like empty strings (TEXT("")). + + STRSAFE_FILL_ON_FAILURE + if the function fails, the low byte of dwFlags will be + used to fill all of the destination buffer, and it will + be null terminated. + + STRSAFE_NO_TRUNCATION / + STRSAFE_NULL_ON_FAILURE + if the function fails, the destination buffer will be set + to the empty string. + +Notes: + pszDest should not be NULL unless the STRSAFE_IGNORE_NULLS flag is specified. + If STRSAFE_IGNORE_NULLS is passed and pszDest is NULL, an error may still be + returned even though NULLS are ignored + + cbDest must be > sizeof(TCHAR) for this function to succeed + +Return Value: + + S_OK - data was read from stdin and copied, and the resultant + dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + STRSAFE_E_END_OF_FILE / + HRESULT_CODE(hr) == ERROR_HANDLE_EOF + - this return value indicates an error or end-of-file + condition, use feof or ferror to determine which one has + occured. + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that there was + insufficient space in the destination buffer to copy any + data + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function. + +--*/ + +#ifndef STRSAFE_LIB_IMPL +STRSAFE_INLINE_API StringCbGetsExA(char* pszDest, size_t cbDest, char** ppszDestEnd, size_t* pbRemaining, unsigned long dwFlags); +STRSAFE_INLINE_API StringCbGetsExW(wchar_t* pszDest, size_t cbDest, wchar_t** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags); +#ifdef UNICODE +#define StringCbGetsEx StringCbGetsExW +#else +#define StringCbGetsEx StringCbGetsExA +#endif // !UNICODE + +STRSAFE_INLINE_API StringCbGetsExA(char* pszDest, size_t cbDest, char** 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) + { + // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1 + *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)); + } + } + + return hr; +} + +STRSAFE_INLINE_API StringCbGetsExW(wchar_t* pszDest, size_t cbDest, wchar_t** 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) + { + // safe to multiply cchRemaining * sizeof(wchar_t) since cchRemaining < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 + *pcbRemaining = (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)); + } + } + + return hr; +} +#endif // !STRSAFE_NO_CB_FUNCTIONS +#endif // !STRSAFE_LIB_IMPL + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI +StringCchLength( + IN LPCTSTR psz, + IN size_t cchMax, + OUT size_t* pcch OPTIONAL + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'strlen'. + It is used to make sure a string is not larger than a given length, and + it optionally returns the current length in characters not including + the null terminator. + + This function returns a hresult, and not a pointer. It returns + S_OK if the string is non-null and the length including the null + terminator is less than or equal to cchMax characters. + +Arguments: + + psz - string to check the length of + + cchMax - maximum number of characters including the null terminator + that psz is allowed to contain + + pcch - if the function succeeds and pcch is non-null, the current length + in characters of psz excluding the null terminator will be returned. + This out parameter is equivalent to the return value of strlen(psz) + +Notes: + psz can be null but the function will fail + + cchMax should be greater than zero or the function will fail + +Return Value: + + S_OK - psz is non-null and the length including the null + terminator is less than or equal to cchMax characters + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function. + +--*/ + +STRSAFEAPI StringCchLengthA(const char* psz, size_t cchMax, size_t* pcch); +STRSAFEAPI StringCchLengthW(const wchar_t* psz, size_t cchMax, size_t* pcch); +#ifdef UNICODE +#define StringCchLength StringCchLengthW +#else +#define StringCchLength StringCchLengthA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCchLengthA(const char* psz, size_t cchMax, size_t* pcch) +{ + HRESULT hr; + + if ((psz == NULL) || (cchMax > STRSAFE_MAX_CCH)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringLengthWorkerA(psz, cchMax, pcch); + } + + return hr; +} + +STRSAFEAPI StringCchLengthW(const wchar_t* psz, size_t cchMax, size_t* pcch) +{ + HRESULT hr; + + if ((psz == NULL) || (cchMax > STRSAFE_MAX_CCH)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringLengthWorkerW(psz, cchMax, pcch); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CCH_FUNCTIONS + + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI +StringCbLength( + IN LPCTSTR psz, + IN size_t cbMax, + OUT size_t* pcb OPTIONAL + ); + +Routine Description: + + This routine is a safer version of the C built-in function 'strlen'. + It is used to make sure a string is not larger than a given length, and + it optionally returns the current length in bytes not including + the null terminator. + + This function returns a hresult, and not a pointer. It returns + S_OK if the string is non-null and the length including the null + terminator is less than or equal to cbMax bytes. + +Arguments: + + psz - string to check the length of + + cbMax - maximum number of bytes including the null terminator + that psz is allowed to contain + + pcb - if the function succeeds and pcb is non-null, the current length + in bytes of psz excluding the null terminator will be returned. + This out parameter is equivalent to the return value of strlen(psz) * sizeof(TCHAR) + +Notes: + psz can be null but the function will fail + + cbMax should be greater than or equal to sizeof(TCHAR) or the function will fail + +Return Value: + + S_OK - psz is non-null and the length including the null + terminator is less than or equal to cbMax bytes + + failure - you can use the macro HRESULT_CODE() to get a win32 + error code for all hresult failure cases + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function. + +--*/ + +STRSAFEAPI StringCbLengthA(const char* psz, size_t cchMax, size_t* pcch); +STRSAFEAPI StringCbLengthW(const wchar_t* psz, size_t cchMax, size_t* pcch); +#ifdef UNICODE +#define StringCbLength StringCbLengthW +#else +#define StringCbLength StringCbLengthA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCbLengthA(const char* psz, size_t cbMax, size_t* pcb) +{ + HRESULT hr; + size_t cchMax; + size_t cch = 0; + + cchMax = cbMax / sizeof(char); + + if ((psz == NULL) || (cchMax > STRSAFE_MAX_CCH)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringLengthWorkerA(psz, cchMax, &cch); + } + + if (SUCCEEDED(hr) && pcb) + { + // safe to multiply cch * sizeof(char) since cch < STRSAFE_MAX_CCH and sizeof(char) is 1 + *pcb = cch * sizeof(char); + } + + return hr; +} + +STRSAFEAPI StringCbLengthW(const wchar_t* psz, size_t cbMax, size_t* pcb) +{ + HRESULT hr; + size_t cchMax; + size_t cch = 0; + + cchMax = cbMax / sizeof(wchar_t); + + if ((psz == NULL) || (cchMax > STRSAFE_MAX_CCH)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringLengthWorkerW(psz, cchMax, &cch); + } + + if (SUCCEEDED(hr) && pcb) + { + // safe to multiply cch * sizeof(wchar_t) since cch < STRSAFE_MAX_CCH and sizeof(wchar_t) is 2 + *pcb = cch * sizeof(wchar_t); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CB_FUNCTIONS + + +// these are the worker functions that actually do the work +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCopyWorkerA(char* pszDest, size_t cchDest, const char* pszSrc) +{ + HRESULT hr = S_OK; + + if (cchDest == 0) + { + // can not null terminate a zero-byte dest buffer + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + while (cchDest && (*pszSrc != '\0')) + { + *pszDest++ = *pszSrc++; + cchDest--; + } + + if (cchDest == 0) + { + // we are going to truncate pszDest + pszDest--; + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + + *pszDest= '\0'; + } + + return hr; +} + +STRSAFEAPI StringCopyWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc) +{ + HRESULT hr = S_OK; + + if (cchDest == 0) + { + // can not null terminate a zero-byte dest buffer + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + while (cchDest && (*pszSrc != L'\0')) + { + *pszDest++ = *pszSrc++; + cchDest--; + } + + if (cchDest == 0) + { + // we are going to truncate pszDest + pszDest--; + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + + *pszDest= L'\0'; + } + + return hr; +} + +STRSAFEAPI StringCopyExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr = S_OK; + char* pszDestEnd = pszDest; + size_t cchRemaining = 0; + + // ASSERT(cbDest == (cchDest * sizeof(char)) || + // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char))); + + // only accept valid flags + if (dwFlags & (~STRSAFE_VALID_FLAGS)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + if (dwFlags & STRSAFE_IGNORE_NULLS) + { + if (pszDest == NULL) + { + if ((cchDest != 0) || (cbDest != 0)) + { + // NULL pszDest and non-zero cchDest/cbDest is invalid + hr = STRSAFE_E_INVALID_PARAMETER; + } + } + + if (pszSrc == NULL) + { + pszSrc = ""; + } + } + + if (SUCCEEDED(hr)) + { + if (cchDest == 0) + { + pszDestEnd = pszDest; + cchRemaining = 0; + + // only fail if there was actually src data to copy + if (*pszSrc != '\0') + { + if (pszDest == NULL) + { + 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 + { + // we are going to truncate pszDest + 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; + + // null terminate the end of the string + *pszDestEnd = '\0'; + } + } + + if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) + { + if (cchDest > 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + // null terminate the beginning of the string + *pszDestEnd = '\0'; + } + } + } + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (ppszDestEnd) + { + *ppszDestEnd = pszDestEnd; + } + + if (pcchRemaining) + { + *pcchRemaining = cchRemaining; + } + } + + return hr; +} + +STRSAFEAPI StringCopyExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr = S_OK; + wchar_t* pszDestEnd = pszDest; + size_t cchRemaining = 0; + + // ASSERT(cbDest == (cchDest * sizeof(wchar_t)) || + // cbDest == (cchDest * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t))); + + // only accept valid flags + if (dwFlags & (~STRSAFE_VALID_FLAGS)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + if (dwFlags & STRSAFE_IGNORE_NULLS) + { + if (pszDest == NULL) + { + if ((cchDest != 0) || (cbDest != 0)) + { + // NULL pszDest and non-zero cchDest/cbDest is invalid + hr = STRSAFE_E_INVALID_PARAMETER; + } + } + + if (pszSrc == NULL) + { + pszSrc = L""; + } + } + + if (SUCCEEDED(hr)) + { + if (cchDest == 0) + { + pszDestEnd = pszDest; + cchRemaining = 0; + + // only fail if there was actually src data to copy + if (*pszSrc != L'\0') + { + if (pszDest == NULL) + { + 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 + { + // we are going to truncate pszDest + 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; + + // null terminate the end of the string + *pszDestEnd = L'\0'; + } + } + + if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) + { + if (cchDest > 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + // null terminate the beginning of the string + *pszDestEnd = L'\0'; + } + } + } + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (ppszDestEnd) + { + *ppszDestEnd = pszDestEnd; + } + + if (pcchRemaining) + { + *pcchRemaining = cchRemaining; + } + } + + return hr; +} + +STRSAFEAPI StringCopyNWorkerA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc) +{ + HRESULT hr = S_OK; + + if (cchDest == 0) + { + // can not null terminate a zero-byte dest buffer + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + while (cchDest && cchSrc && (*pszSrc != '\0')) + { + *pszDest++= *pszSrc++; + cchDest--; + cchSrc--; + } + + if (cchDest == 0) + { + // we are going to truncate pszDest + pszDest--; + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + + *pszDest= '\0'; + } + + return hr; +} + +STRSAFEAPI StringCopyNWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchSrc) +{ + HRESULT hr = S_OK; + + if (cchDest == 0) + { + // can not null terminate a zero-byte dest buffer + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + while (cchDest && cchSrc && (*pszSrc != L'\0')) + { + *pszDest++= *pszSrc++; + cchDest--; + cchSrc--; + } + + if (cchDest == 0) + { + // we are going to truncate pszDest + pszDest--; + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + + *pszDest= L'\0'; + } + + return hr; +} + +STRSAFEAPI StringCopyNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, size_t cchSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr = S_OK; + char* pszDestEnd = pszDest; + size_t cchRemaining = 0; + + // ASSERT(cbDest == (cchDest * sizeof(char)) || + // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char))); + + // only accept valid flags + if (dwFlags & (~STRSAFE_VALID_FLAGS)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + if (dwFlags & STRSAFE_IGNORE_NULLS) + { + if (pszDest == NULL) + { + if ((cchDest != 0) || (cbDest != 0)) + { + // NULL pszDest and non-zero cchDest/cbDest is invalid + hr = STRSAFE_E_INVALID_PARAMETER; + } + } + + if (pszSrc == NULL) + { + pszSrc = ""; + } + } + + if (SUCCEEDED(hr)) + { + if (cchDest == 0) + { + pszDestEnd = pszDest; + cchRemaining = 0; + + // only fail if there was actually src data to copy + if (*pszSrc != '\0') + { + if (pszDest == NULL) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + } + } + else + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + while (cchRemaining && cchSrc && (*pszSrc != '\0')) + { + *pszDestEnd++= *pszSrc++; + cchRemaining--; + cchSrc--; + } + + 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 + { + // we are going to truncate pszDest + 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; + + // null terminate the end of the string + *pszDestEnd = '\0'; + } + } + + if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) + { + if (cchDest > 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + // null terminate the beginning of the string + *pszDestEnd = '\0'; + } + } + } + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (ppszDestEnd) + { + *ppszDestEnd = pszDestEnd; + } + + if (pcchRemaining) + { + *pcchRemaining = cchRemaining; + } + } + + return hr; +} + +STRSAFEAPI StringCopyNExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, const wchar_t* pszSrc, size_t cchSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr = S_OK; + wchar_t* pszDestEnd = pszDest; + size_t cchRemaining = 0; + + // ASSERT(cbDest == (cchDest * sizeof(wchar_t)) || + // cbDest == (cchDest * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t))); + + // only accept valid flags + if (dwFlags & (~STRSAFE_VALID_FLAGS)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + if (dwFlags & STRSAFE_IGNORE_NULLS) + { + if (pszDest == NULL) + { + if ((cchDest != 0) || (cbDest != 0)) + { + // NULL pszDest and non-zero cchDest/cbDest is invalid + hr = STRSAFE_E_INVALID_PARAMETER; + } + } + + if (pszSrc == NULL) + { + pszSrc = L""; + } + } + + if (SUCCEEDED(hr)) + { + if (cchDest == 0) + { + pszDestEnd = pszDest; + cchRemaining = 0; + + // only fail if there was actually src data to copy + if (*pszSrc != L'\0') + { + if (pszDest == NULL) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + } + } + else + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + while (cchRemaining && cchSrc && (*pszSrc != L'\0')) + { + *pszDestEnd++= *pszSrc++; + cchRemaining--; + cchSrc--; + } + + 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 + { + // we are going to truncate pszDest + 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; + + // null terminate the end of the string + *pszDestEnd = L'\0'; + } + } + + if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) + { + if (cchDest > 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + // null terminate the beginning of the string + *pszDestEnd = L'\0'; + } + } + } + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (ppszDestEnd) + { + *ppszDestEnd = pszDestEnd; + } + + if (pcchRemaining) + { + *pcchRemaining = cchRemaining; + } + } + + return hr; +} + +STRSAFEAPI StringCatWorkerA(char* pszDest, size_t cchDest, const char* pszSrc) +{ + HRESULT hr; + size_t cchDestCurrent; + + hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent); + + if (SUCCEEDED(hr)) + { + hr = StringCopyWorkerA(pszDest + cchDestCurrent, + cchDest - cchDestCurrent, + pszSrc); + } + + return hr; +} + +STRSAFEAPI StringCatWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc) +{ + HRESULT hr; + size_t cchDestCurrent; + + hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent); + + if (SUCCEEDED(hr)) + { + hr = StringCopyWorkerW(pszDest + cchDestCurrent, + cchDest - cchDestCurrent, + pszSrc); + } + + return hr; +} + +STRSAFEAPI StringCatExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr = S_OK; + char* pszDestEnd = pszDest; + size_t cchRemaining = 0; + + // ASSERT(cbDest == (cchDest * sizeof(char)) || + // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char))); + + // only accept valid flags + if (dwFlags & (~STRSAFE_VALID_FLAGS)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cchDestCurrent; + + if (dwFlags & STRSAFE_IGNORE_NULLS) + { + if (pszDest == NULL) + { + if ((cchDest == 0) && (cbDest == 0)) + { + cchDestCurrent = 0; + } + else + { + // NULL pszDest and non-zero cchDest/cbDest is invalid + hr = STRSAFE_E_INVALID_PARAMETER; + } + } + else + { + hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent); + + if (SUCCEEDED(hr)) + { + pszDestEnd = pszDest + cchDestCurrent; + cchRemaining = cchDest - cchDestCurrent; + } + } + + if (pszSrc == NULL) + { + pszSrc = ""; + } + } + else + { + hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent); + + if (SUCCEEDED(hr)) + { + pszDestEnd = pszDest + cchDestCurrent; + cchRemaining = cchDest - cchDestCurrent; + } + } + + if (SUCCEEDED(hr)) + { + if (cchDest == 0) + { + // only fail if there was actually src data to append + if (*pszSrc != '\0') + { + if (pszDest == NULL) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + } + } + else + { + // we handle the STRSAFE_FILL_ON_FAILURE and STRSAFE_NULL_ON_FAILURE cases below, so do not pass + // those flags through + 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) + { + // STRSAFE_NO_TRUNCATION is taken care of by StringCopyExWorkerA() + + 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; + + // null terminate the end of the string + *pszDestEnd = '\0'; + } + } + + if (dwFlags & STRSAFE_NULL_ON_FAILURE) + { + if (cchDest > 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + // null terminate the beginning of the string + *pszDestEnd = '\0'; + } + } + } + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (ppszDestEnd) + { + *ppszDestEnd = pszDestEnd; + } + + if (pcchRemaining) + { + *pcchRemaining = cchRemaining; + } + } + + return hr; +} + +STRSAFEAPI StringCatExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, const wchar_t* pszSrc, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr = S_OK; + wchar_t* pszDestEnd = pszDest; + size_t cchRemaining = 0; + + // ASSERT(cbDest == (cchDest * sizeof(wchar_t)) || + // cbDest == (cchDest * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t))); + + // only accept valid flags + if (dwFlags & (~STRSAFE_VALID_FLAGS)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cchDestCurrent; + + if (dwFlags & STRSAFE_IGNORE_NULLS) + { + if (pszDest == NULL) + { + if ((cchDest == 0) && (cbDest == 0)) + { + cchDestCurrent = 0; + } + else + { + // NULL pszDest and non-zero cchDest/cbDest is invalid + hr = STRSAFE_E_INVALID_PARAMETER; + } + } + else + { + hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent); + + if (SUCCEEDED(hr)) + { + pszDestEnd = pszDest + cchDestCurrent; + cchRemaining = cchDest - cchDestCurrent; + } + } + + if (pszSrc == NULL) + { + pszSrc = L""; + } + } + else + { + hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent); + + if (SUCCEEDED(hr)) + { + pszDestEnd = pszDest + cchDestCurrent; + cchRemaining = cchDest - cchDestCurrent; + } + } + + if (SUCCEEDED(hr)) + { + if (cchDest == 0) + { + // only fail if there was actually src data to append + if (*pszSrc != L'\0') + { + if (pszDest == NULL) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + } + } + else + { + // we handle the STRSAFE_FILL_ON_FAILURE and STRSAFE_NULL_ON_FAILURE cases below, so do not pass + // those flags through + 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) + { + // STRSAFE_NO_TRUNCATION is taken care of by StringCopyExWorkerW() + + 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; + + // null terminate the end of the string + *pszDestEnd = L'\0'; + } + } + + if (dwFlags & STRSAFE_NULL_ON_FAILURE) + { + if (cchDest > 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + // null terminate the beginning of the string + *pszDestEnd = L'\0'; + } + } + } + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (ppszDestEnd) + { + *ppszDestEnd = pszDestEnd; + } + + if (pcchRemaining) + { + *pcchRemaining = cchRemaining; + } + } + + return hr; +} + +STRSAFEAPI StringCatNWorkerA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend) +{ + HRESULT hr; + size_t cchDestCurrent; + + hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent); + + if (SUCCEEDED(hr)) + { + hr = StringCopyNWorkerA(pszDest + cchDestCurrent, + cchDest - cchDestCurrent, + pszSrc, + cchMaxAppend); + } + + return hr; +} + +STRSAFEAPI StringCatNWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc, size_t cchMaxAppend) +{ + HRESULT hr; + size_t cchDestCurrent; + + hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent); + + if (SUCCEEDED(hr)) + { + hr = StringCopyNWorkerW(pszDest + cchDestCurrent, + cchDest - cchDestCurrent, + pszSrc, + cchMaxAppend); + } + + return hr; +} + +STRSAFEAPI StringCatNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, size_t cchMaxAppend, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr = S_OK; + char* pszDestEnd = pszDest; + size_t cchRemaining = 0; + size_t cchDestCurrent = 0; + + // ASSERT(cbDest == (cchDest * sizeof(char)) || + // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char))); + + // only accept valid flags + if (dwFlags & (~STRSAFE_VALID_FLAGS)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + if (dwFlags & STRSAFE_IGNORE_NULLS) + { + if (pszDest == NULL) + { + if ((cchDest == 0) && (cbDest == 0)) + { + cchDestCurrent = 0; + } + else + { + // NULL pszDest and non-zero cchDest/cbDest is invalid + hr = STRSAFE_E_INVALID_PARAMETER; + } + } + else + { + hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent); + + if (SUCCEEDED(hr)) + { + pszDestEnd = pszDest + cchDestCurrent; + cchRemaining = cchDest - cchDestCurrent; + } + } + + if (pszSrc == NULL) + { + pszSrc = ""; + } + } + else + { + hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent); + + if (SUCCEEDED(hr)) + { + pszDestEnd = pszDest + cchDestCurrent; + cchRemaining = cchDest - cchDestCurrent; + } + } + + if (SUCCEEDED(hr)) + { + if (cchDest == 0) + { + // only fail if there was actually src data to append + if (*pszSrc != '\0') + { + if (pszDest == NULL) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + } + } + else + { + // we handle the STRSAFE_FILL_ON_FAILURE and STRSAFE_NULL_ON_FAILURE cases below, so do not pass + // those flags through + hr = StringCopyNExWorkerA(pszDestEnd, + cchRemaining, + (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)), + pszSrc, + cchMaxAppend, + &pszDestEnd, + &cchRemaining, + dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE))); + } + } + } + + if (FAILED(hr)) + { + if (pszDest) + { + // STRSAFE_NO_TRUNCATION is taken care of by StringCopyNExWorkerA() + + 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; + + // null terminate the end of the string + *pszDestEnd = '\0'; + } + } + + if (dwFlags & (STRSAFE_NULL_ON_FAILURE)) + { + if (cchDest > 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + // null terminate the beginning of the string + *pszDestEnd = '\0'; + } + } + } + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (ppszDestEnd) + { + *ppszDestEnd = pszDestEnd; + } + + if (pcchRemaining) + { + *pcchRemaining = cchRemaining; + } + } + + return hr; +} + +STRSAFEAPI StringCatNExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, const wchar_t* pszSrc, size_t cchMaxAppend, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr = S_OK; + wchar_t* pszDestEnd = pszDest; + size_t cchRemaining = 0; + size_t cchDestCurrent = 0; + + + // ASSERT(cbDest == (cchDest * sizeof(wchar_t)) || + // cbDest == (cchDest * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t))); + + // only accept valid flags + if (dwFlags & (~STRSAFE_VALID_FLAGS)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + if (dwFlags & STRSAFE_IGNORE_NULLS) + { + if (pszDest == NULL) + { + if ((cchDest == 0) && (cbDest == 0)) + { + cchDestCurrent = 0; + } + else + { + // NULL pszDest and non-zero cchDest/cbDest is invalid + hr = STRSAFE_E_INVALID_PARAMETER; + } + } + else + { + hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent); + + if (SUCCEEDED(hr)) + { + pszDestEnd = pszDest + cchDestCurrent; + cchRemaining = cchDest - cchDestCurrent; + } + } + + if (pszSrc == NULL) + { + pszSrc = L""; + } + } + else + { + hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent); + + if (SUCCEEDED(hr)) + { + pszDestEnd = pszDest + cchDestCurrent; + cchRemaining = cchDest - cchDestCurrent; + } + } + + if (SUCCEEDED(hr)) + { + if (cchDest == 0) + { + // only fail if there was actually src data to append + if (*pszSrc != L'\0') + { + if (pszDest == NULL) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + } + } + else + { + // we handle the STRSAFE_FILL_ON_FAILURE and STRSAFE_NULL_ON_FAILURE cases below, so do not pass + // those flags through + hr = StringCopyNExWorkerW(pszDestEnd, + cchRemaining, + (cchRemaining * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)), + pszSrc, + cchMaxAppend, + &pszDestEnd, + &cchRemaining, + dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE))); + } + } + } + + if (FAILED(hr)) + { + if (pszDest) + { + // STRSAFE_NO_TRUNCATION is taken care of by StringCopyNExWorkerW() + + 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; + + // null terminate the end of the string + *pszDestEnd = L'\0'; + } + } + + if (dwFlags & (STRSAFE_NULL_ON_FAILURE)) + { + if (cchDest > 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + // null terminate the beginning of the string + *pszDestEnd = L'\0'; + } + } + } + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (ppszDestEnd) + { + *ppszDestEnd = pszDestEnd; + } + + if (pcchRemaining) + { + *pcchRemaining = cchRemaining; + } + } + + return hr; +} + +STRSAFEAPI StringVPrintfWorkerA(char* pszDest, size_t cchDest, const char* pszFormat, va_list argList) +{ + HRESULT hr = S_OK; + + if (cchDest == 0) + { + // can not null terminate a zero-byte dest buffer + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + int iRet; + size_t cchMax; + + // leave the last space for the null terminator + cchMax = cchDest - 1; + + iRet = _vsnprintf(pszDest, cchMax, pszFormat, argList); + // ASSERT((iRet < 0) || (((size_t)iRet) <= cchMax)); + + if ((iRet < 0) || (((size_t)iRet) > cchMax)) + { + // need to null terminate the string + pszDest += cchMax; + *pszDest = '\0'; + + // we have truncated pszDest + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + else if (((size_t)iRet) == cchMax) + { + // need to null terminate the string + pszDest += cchMax; + *pszDest = '\0'; + } + } + + return hr; +} + +STRSAFEAPI StringVPrintfWorkerW(wchar_t* pszDest, size_t cchDest, const wchar_t* pszFormat, va_list argList) +{ + HRESULT hr = S_OK; + + if (cchDest == 0) + { + // can not null terminate a zero-byte dest buffer + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + int iRet; + size_t cchMax; + + // leave the last space for the null terminator + cchMax = cchDest - 1; + + iRet = _vsnwprintf(pszDest, cchMax, pszFormat, argList); + // ASSERT((iRet < 0) || (((size_t)iRet) <= cchMax)); + + if ((iRet < 0) || (((size_t)iRet) > cchMax)) + { + // need to null terminate the string + pszDest += cchMax; + *pszDest = L'\0'; + + // we have truncated pszDest + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + else if (((size_t)iRet) == cchMax) + { + // need to null terminate the string + pszDest += cchMax; + *pszDest = L'\0'; + } + } + + return hr; +} + +STRSAFEAPI StringVPrintfExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const char* pszFormat, va_list argList) +{ + HRESULT hr = S_OK; + char* pszDestEnd = pszDest; + size_t cchRemaining = 0; + + // ASSERT(cbDest == (cchDest * sizeof(char)) || + // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char))); + + // only accept valid flags + if (dwFlags & (~STRSAFE_VALID_FLAGS)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + if (dwFlags & STRSAFE_IGNORE_NULLS) + { + if (pszDest == NULL) + { + if ((cchDest != 0) || (cbDest != 0)) + { + // NULL pszDest and non-zero cchDest/cbDest is invalid + hr = STRSAFE_E_INVALID_PARAMETER; + } + } + + if (pszFormat == NULL) + { + pszFormat = ""; + } + } + + if (SUCCEEDED(hr)) + { + if (cchDest == 0) + { + pszDestEnd = pszDest; + cchRemaining = 0; + + // only fail if there was actually a non-empty format string + if (*pszFormat != '\0') + { + if (pszDest == NULL) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + } + } + else + { + int iRet; + size_t cchMax; + + // leave the last space for the null terminator + cchMax = cchDest - 1; + + iRet = _vsnprintf(pszDest, cchMax, pszFormat, argList); + // ASSERT((iRet < 0) || (((size_t)iRet) <= cchMax)); + + if ((iRet < 0) || (((size_t)iRet) > cchMax)) + { + // we have truncated pszDest + pszDestEnd = pszDest + cchMax; + cchRemaining = 1; + + // need to null terminate the string + *pszDestEnd = '\0'; + + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + else if (((size_t)iRet) == cchMax) + { + // string fit perfectly + pszDestEnd = pszDest + cchMax; + cchRemaining = 1; + + // need to null terminate the string + *pszDestEnd = '\0'; + } + else if (((size_t)iRet) < cchMax) + { + // there is extra room + 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; + + // null terminate the end of the string + *pszDestEnd = '\0'; + } + } + + if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) + { + if (cchDest > 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + // null terminate the beginning of the string + *pszDestEnd = '\0'; + } + } + } + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (ppszDestEnd) + { + *ppszDestEnd = pszDestEnd; + } + + if (pcchRemaining) + { + *pcchRemaining = cchRemaining; + } + } + + return hr; +} + +STRSAFEAPI StringVPrintfExWorkerW(wchar_t* pszDest, size_t cchDest, size_t cbDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags, const wchar_t* pszFormat, va_list argList) +{ + HRESULT hr = S_OK; + wchar_t* pszDestEnd = pszDest; + size_t cchRemaining = 0; + + // ASSERT(cbDest == (cchDest * sizeof(wchar_t)) || + // cbDest == (cchDest * sizeof(wchar_t)) + (cbDest % sizeof(wchar_t))); + + // only accept valid flags + if (dwFlags & (~STRSAFE_VALID_FLAGS)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + if (dwFlags & STRSAFE_IGNORE_NULLS) + { + if (pszDest == NULL) + { + if ((cchDest != 0) || (cbDest != 0)) + { + // NULL pszDest and non-zero cchDest/cbDest is invalid + hr = STRSAFE_E_INVALID_PARAMETER; + } + } + + if (pszFormat == NULL) + { + pszFormat = L""; + } + } + + if (SUCCEEDED(hr)) + { + if (cchDest == 0) + { + pszDestEnd = pszDest; + cchRemaining = 0; + + // only fail if there was actually a non-empty format string + if (*pszFormat != L'\0') + { + if (pszDest == NULL) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + } + } + else + { + int iRet; + size_t cchMax; + + // leave the last space for the null terminator + cchMax = cchDest - 1; + + iRet = _vsnwprintf(pszDest, cchMax, pszFormat, argList); + // ASSERT((iRet < 0) || (((size_t)iRet) <= cchMax)); + + if ((iRet < 0) || (((size_t)iRet) > cchMax)) + { + // we have truncated pszDest + pszDestEnd = pszDest + cchMax; + cchRemaining = 1; + + // need to null terminate the string + *pszDestEnd = L'\0'; + + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + else if (((size_t)iRet) == cchMax) + { + // string fit perfectly + pszDestEnd = pszDest + cchMax; + cchRemaining = 1; + + // need to null terminate the string + *pszDestEnd = L'\0'; + } + else if (((size_t)iRet) < cchMax) + { + // there is extra room + 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; + + // null terminate the end of the string + *pszDestEnd = L'\0'; + } + } + + if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) + { + if (cchDest > 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + // null terminate the beginning of the string + *pszDestEnd = L'\0'; + } + } + } + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (ppszDestEnd) + { + *ppszDestEnd = pszDestEnd; + } + + if (pcchRemaining) + { + *pcchRemaining = cchRemaining; + } + } + + return hr; +} + +STRSAFEAPI StringLengthWorkerA(const char* psz, size_t cchMax, size_t* pcch) +{ + HRESULT hr = S_OK; + size_t cchMaxPrev = cchMax; + + while (cchMax && (*psz != '\0')) + { + psz++; + cchMax--; + } + + if (cchMax == 0) + { + // the string is longer than cchMax + hr = STRSAFE_E_INVALID_PARAMETER; + } + + if (SUCCEEDED(hr) && pcch) + { + *pcch = cchMaxPrev - cchMax; + } + + return hr; +} + +STRSAFEAPI StringLengthWorkerW(const wchar_t* psz, size_t cchMax, size_t* pcch) +{ + HRESULT hr = S_OK; + size_t cchMaxPrev = cchMax; + + while (cchMax && (*psz != L'\0')) + { + psz++; + cchMax--; + } + + if (cchMax == 0) + { + // the string is longer than cchMax + hr = STRSAFE_E_INVALID_PARAMETER; + } + + if (SUCCEEDED(hr) && pcch) + { + *pcch = cchMaxPrev - cchMax; + } + + return hr; +} +#endif // STRSAFE_INLINE + +#ifndef STRSAFE_LIB_IMPL +STRSAFE_INLINE_API StringGetsExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr = S_OK; + char* pszDestEnd = pszDest; + size_t cchRemaining = 0; + + // ASSERT(cbDest == (cchDest * sizeof(char)) || + // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char))); + + // only accept valid flags + if (dwFlags & (~STRSAFE_VALID_FLAGS)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + if (dwFlags & STRSAFE_IGNORE_NULLS) + { + if (pszDest == NULL) + { + if ((cchDest != 0) || (cbDest != 0)) + { + // NULL pszDest and non-zero cchDest/cbDest is invalid + 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 + { + char ch; + + pszDestEnd = pszDest; + cchRemaining = cchDest; + + while ((cchRemaining > 1) && (ch = (char)getc(stdin)) != '\n') + { + if (ch == EOF) + { + if (pszDestEnd == pszDest) + { + // we failed to read anything from stdin + hr = STRSAFE_E_END_OF_FILE; + } + break; + } + + *pszDestEnd = ch; + + pszDestEnd++; + cchRemaining--; + } + + if (cchRemaining > 0) + { + // there is extra room + 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; + + // null terminate the end of the string + *pszDestEnd = '\0'; + } + } + + if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) + { + if (cchDest > 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + // null terminate the beginning of the string + *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(wchar_t* pszDest, size_t cchDest, size_t cbDest, wchar_t** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr = S_OK; + wchar_t* pszDestEnd = pszDest; + size_t cchRemaining = 0; + + // ASSERT(cbDest == (cchDest * sizeof(char)) || + // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char))); + + // only accept valid flags + if (dwFlags & (~STRSAFE_VALID_FLAGS)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + if (dwFlags & STRSAFE_IGNORE_NULLS) + { + if (pszDest == NULL) + { + if ((cchDest != 0) || (cbDest != 0)) + { + // NULL pszDest and non-zero cchDest/cbDest is invalid + 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 + { + wchar_t ch; + + pszDestEnd = pszDest; + cchRemaining = cchDest; + + while ((cchRemaining > 1) && (ch = (wchar_t)getwc(stdin)) != L'\n') + { + if (ch == EOF) + { + if (pszDestEnd == pszDest) + { + // we failed to read anything from stdin + hr = STRSAFE_E_END_OF_FILE; + } + break; + } + + *pszDestEnd = ch; + + pszDestEnd++; + cchRemaining--; + } + + if (cchRemaining > 0) + { + // there is extra room + 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; + + // null terminate the end of the string + *pszDestEnd = L'\0'; + } + } + + if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) + { + if (cchDest > 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + // null terminate the beginning of the string + *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 // !STRSAFE_LIB_IMPL + + +// Do not call these functions, they are worker functions for internal use within this file +#ifdef DEPRECATE_SUPPORTED +#pragma deprecated(StringCopyWorkerA) +#pragma deprecated(StringCopyWorkerW) +#pragma deprecated(StringCopyExWorkerA) +#pragma deprecated(StringCopyExWorkerW) +#pragma deprecated(StringCatWorkerA) +#pragma deprecated(StringCatWorkerW) +#pragma deprecated(StringCatExWorkerA) +#pragma deprecated(StringCatExWorkerW) +#pragma deprecated(StringCatNWorkerA) +#pragma deprecated(StringCatNWorkerW) +#pragma deprecated(StringCatNExWorkerA) +#pragma deprecated(StringCatNExWorkerW) +#pragma deprecated(StringVPrintfWorkerA) +#pragma deprecated(StringVPrintfWorkerW) +#pragma deprecated(StringVPrintfExWorkerA) +#pragma deprecated(StringVPrintfExWorkerW) +#pragma deprecated(StringLengthWorkerA) +#pragma deprecated(StringLengthWorkerW) +#else +#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; +#endif // !DEPRECATE_SUPPORTED + + +#ifndef STRSAFE_NO_DEPRECATE +// Deprecate all of the unsafe functions to generate compiletime errors. If you do not want +// this then you can #define STRSAFE_NO_DEPRECATE before including this file. +#ifdef DEPRECATE_SUPPORTED + +// First all the names that are a/w variants (or shouldn't be #defined by now anyway). +#pragma deprecated(lstrcpyA) +#pragma deprecated(lstrcpyW) +#pragma deprecated(lstrcatA) +#pragma deprecated(lstrcatW) +#pragma deprecated(wsprintfA) +#pragma deprecated(wsprintfW) + +#pragma deprecated(StrCpyW) +#pragma deprecated(StrCatW) +#pragma deprecated(StrNCatA) +#pragma deprecated(StrNCatW) +#pragma deprecated(StrCatNA) +#pragma deprecated(StrCatNW) +#pragma deprecated(wvsprintfA) +#pragma deprecated(wvsprintfW) + +#pragma deprecated(strcpy) +#pragma deprecated(wcscpy) +#pragma deprecated(strcat) +#pragma deprecated(wcscat) +#pragma deprecated(sprintf) +#pragma deprecated(swprintf) +#pragma deprecated(vsprintf) +#pragma deprecated(vswprintf) +#pragma deprecated(_snprintf) +#pragma deprecated(_snwprintf) +#pragma deprecated(_vsnprintf) +#pragma deprecated(_vsnwprintf) +#pragma deprecated(gets) +#pragma deprecated(_getws) + +// Then all the windows.h names - we need to undef and redef based on UNICODE setting +#undef lstrcpy +#undef lstrcat +#undef wsprintf +#undef wvsprintf +#pragma deprecated(lstrcpy) +#pragma deprecated(lstrcat) +#pragma deprecated(wsprintf) +#pragma deprecated(wvsprintf) +#ifdef UNICODE +#define lstrcpy lstrcpyW +#define lstrcat lstrcatW +#define wsprintf wsprintfW +#define wvsprintf wvsprintfW +#else +#define lstrcpy lstrcpyA +#define lstrcat lstrcatA +#define wsprintf wsprintfA +#define wvsprintf wvsprintfA +#endif + +// Then the shlwapi names - they key off UNICODE also. +#undef StrCpyA +#undef StrCpy +#undef StrCatA +#undef StrCat +#undef StrNCat +#undef StrCatN +#pragma deprecated(StrCpyA) +#pragma deprecated(StrCatA) +#pragma deprecated(StrCatN) +#pragma deprecated(StrCpy) +#pragma deprecated(StrCat) +#pragma deprecated(StrNCat) +#define StrCpyA lstrcpyA +#define StrCatA lstrcatA +#define StrCatN StrNCat +#ifdef UNICODE +#define StrCpy StrCpyW +#define StrCat StrCatW +#define StrNCat StrNCatW +#else +#define StrCpy lstrcpyA +#define StrCat lstrcatA +#define StrNCat StrNCatA +#endif + +// Then all the CRT names - we need to undef/redef based on _UNICODE value. +#undef _tcscpy +#undef _ftcscpy +#undef _tcscat +#undef _ftcscat +#undef _stprintf +#undef _sntprintf +#undef _vstprintf +#undef _vsntprintf +#undef _getts +#pragma deprecated(_tcscpy) +#pragma deprecated(_ftcscpy) +#pragma deprecated(_tcscat) +#pragma deprecated(_ftcscat) +#pragma deprecated(_stprintf) +#pragma deprecated(_sntprintf) +#pragma deprecated(_vstprintf) +#pragma deprecated(_vsntprintf) +#pragma deprecated(_getts) +#ifdef _UNICODE +#define _tcscpy wcscpy +#define _ftcscpy wcscpy +#define _tcscat wcscat +#define _ftcscat wcscat +#define _stprintf swprintf +#define _sntprintf _snwprintf +#define _vstprintf vswprintf +#define _vsntprintf _vsnwprintf +#define _getts _getws +#else +#define _tcscpy strcpy +#define _ftcscpy strcpy +#define _tcscat strcat +#define _ftcscat strcat +#define _stprintf sprintf +#define _sntprintf _snprintf +#define _vstprintf vsprintf +#define _vsntprintf _vsnprintf +#define _getts gets +#endif + +#else // DEPRECATE_SUPPORTED + +#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 // !DEPRECATE_SUPPORTED +#endif // !STRSAFE_NO_DEPRECATE + +#ifdef _NTSTRSAFE_H_INCLUDED_ +#pragma warning(pop) +#endif // _NTSTRSAFE_H_INCLUDED_ + +#endif // _STRSAFE_H_INCLUDED_ diff --git a/cpp/pipe/src/pipe.c b/cpp/pipe/src/pipe.c new file mode 100644 index 0000000..c83c76d --- /dev/null +++ b/cpp/pipe/src/pipe.c @@ -0,0 +1,262 @@ +#include +#include +#include +#include "pipe.h" + +#define DEBUG 0 + +JNIEXPORT jint JNICALL Java_pipe_Pipes_CreateNamedPipe +( + JNIEnv *env, + jclass className, + jstring sPipeName, + jint dwOpenMode, + jint dwPipeMode, + jint nMaxInstances, + jint nOutBufferSize, + jint nInBufferSize, + jint nDefaultTimeOut, + jint lpSecurityAttributes + ) +{ + HANDLE pipeHandler; + LPCSTR pipeName; + pipeName = (*env)->GetStringUTFChars(env, sPipeName, NULL); + if (pipeName == NULL) + return -1; + + if (DEBUG) + { + printf("Native: Pipe Name %s\n", pipeName); + printf("Native: dwOpenMode %d\n", dwOpenMode); + printf("Native: dwPipeMode %d\n", dwPipeMode); + printf("Native: nMaxInstances %d\n", nMaxInstances); + printf("Native: nOutBufferSize %d\n", nOutBufferSize); + printf("Native: nInBufferSize %d\n", nInBufferSize); + printf("Native: nDefaultTimeOut %d\n", nDefaultTimeOut); + } + + pipeHandler = CreateNamedPipe((LPCSTR)pipeName, dwOpenMode, dwPipeMode, nMaxInstances, nOutBufferSize, nInBufferSize, + nDefaultTimeOut, (LPSECURITY_ATTRIBUTES) lpSecurityAttributes); + + (*env)->ReleaseStringUTFChars(env, sPipeName, pipeName); + return (jint) pipeHandler; +} + +JNIEXPORT jboolean JNICALL Java_pipe_Pipes_ConnectNamedPipe +( + JNIEnv *env, + jclass className, + jint hNamedPipe, + jint lpOverlapped + ) +{ + BOOL fConnected; + HANDLE pipeHandler = (HANDLE) hNamedPipe; + fConnected = ConnectNamedPipe(pipeHandler, (LPOVERLAPPED) lpOverlapped); + return fConnected; +} + +JNIEXPORT jint JNICALL Java_pipe_Pipes_GetLastError +( + JNIEnv *env, + jclass className + ) +{ + DWORD errorNumber = GetLastError(); + return (jint) errorNumber; +} + +JNIEXPORT jboolean JNICALL Java_pipe_Pipes_CloseHandle +( + JNIEnv *env, + jclass className, + jint hNamedPipe + ) +{ + BOOL result; + HANDLE pipeHandler = (HANDLE) hNamedPipe; + result = CloseHandle(pipeHandler); + return result; +} + +JNIEXPORT jbyteArray JNICALL Java_pipe_Pipes_ReadFile +( + JNIEnv *env, + jclass className, + jint hNamedPipe, + jint nNumberOfBytesToRead + ) +{ + int bytesRead = 0; + BOOL result; + HANDLE pipeHandler = (HANDLE) hNamedPipe; + LPVOID buffer; + jbyteArray lpBuffer; + + buffer = (LPVOID)LocalAlloc(LMEM_ZEROINIT, nNumberOfBytesToRead); + + if (DEBUG) + { + printf("Native: Before ReadFile pipeHandler %d nNumberOfBytesToRead %d\n", pipeHandler, nNumberOfBytesToRead); + } + result = ReadFile(pipeHandler, (LPVOID) buffer, (DWORD) nNumberOfBytesToRead, &bytesRead, (LPOVERLAPPED) 0); + if (result) + { + lpBuffer = (*env)->NewByteArray(env, (jsize) bytesRead); + (*env)->SetByteArrayRegion(env, lpBuffer, 0, (jsize) bytesRead, (jbyte *) buffer); + } else + bytesRead = 0; + + LocalFree(buffer); + + if (DEBUG) + { + printf("Native: After ReadFile BytesRead %d\n", bytesRead); + } + return lpBuffer; +} + +JNIEXPORT jint JNICALL Java_pipe_Pipes_WriteFile +( + JNIEnv *env, + jclass className, + jint hNamedPipe, + jbyteArray lpBuffer, + jint nNumberOfBytesToWrite + ) +{ + int bytesWritten = 0; + BOOL result; + HANDLE pipeHandler = (HANDLE) hNamedPipe; + LPVOID buffer; + + buffer = (LPVOID)LocalAlloc(LMEM_ZEROINIT, nNumberOfBytesToWrite); + + (*env)->GetByteArrayRegion(env, lpBuffer, 0, nNumberOfBytesToWrite, buffer); + result = WriteFile(pipeHandler, buffer, (DWORD) nNumberOfBytesToWrite, (LPDWORD) &bytesWritten, (LPOVERLAPPED) 0); + LocalFree(buffer); + + if (DEBUG) + { + printf("Native: After WriteFile BytesReadWritten %d\n", bytesWritten); + } + + if (!result) + { + if (GetLastError() != ERROR_IO_PENDING) + result = 0; + else + result = 1; + } + if (!result) + { + bytesWritten = -1; + } + return bytesWritten; +} + +JNIEXPORT jboolean JNICALL Java_pipe_Pipes_FlushFileBuffers +( + JNIEnv *env, + jclass className, + jint hNamedPipe + ) +{ + BOOL result; + HANDLE pipeHandler = (HANDLE) hNamedPipe; + result = FlushFileBuffers(pipeHandler); + return result; +} + +JNIEXPORT jboolean JNICALL Java_pipe_Pipes_DisconnectNamedPipe +( + JNIEnv *env, + jclass className, + jint hNamedPipe + ) +{ + BOOL result; + HANDLE pipeHandler = (HANDLE) hNamedPipe; + result = DisconnectNamedPipe(pipeHandler); + return result; +} + +JNIEXPORT jint JNICALL Java_pipe_Pipes_CreateFile +( + JNIEnv *env, + jclass className, + jstring lpFileName, + jint dwDesiredAccess, + jint dwShareMode, + jint lpSecurityAttributes, + jint dwCreationDisposition, + jint dwFlagsAndAttributes, + jint hTemplateFile + ) +{ + HANDLE pipeHandler; + const jbyte *fileName; + fileName = (*env)->GetStringUTFChars(env, lpFileName, NULL); + if (fileName == NULL) + return -1; + pipeHandler = CreateFile((LPCSTR) fileName, (DWORD) dwDesiredAccess, (DWORD) dwShareMode, + (LPSECURITY_ATTRIBUTES) lpSecurityAttributes, (DWORD) dwCreationDisposition, (DWORD) dwFlagsAndAttributes, (HANDLE) hTemplateFile); + return (jint) pipeHandler; +} + +JNIEXPORT jboolean JNICALL Java_pipe_Pipes_WaitNamedPipe +( + JNIEnv *env, + jclass className, + jstring lpNamedPipeName, + jint nTimeOut + ) +{ + BOOL result; + const jbyte *pipeName; + pipeName = (*env)->GetStringUTFChars(env, lpNamedPipeName, NULL); + if (pipeName == NULL) + return 0; + result = WaitNamedPipe((LPCSTR) pipeName, (DWORD) nTimeOut); + return result; +} + +JNIEXPORT jstring JNICALL Java_pipe_Pipes_FormatMessage +( + JNIEnv *env, + jclass className, + jint errorCode +) +{ + LPVOID lpMsgBuf; + LPVOID lpDisplayBuf; + DWORD dw = (DWORD) errorCode; + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + dw, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, + 0, NULL ); + + lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, + (lstrlen((LPCTSTR)lpMsgBuf) + 40) * sizeof(TCHAR)); + StringCchPrintf((LPTSTR)lpDisplayBuf, LocalSize(lpDisplayBuf) / sizeof(TCHAR), + TEXT("Failed with error %d: %s"), dw, lpMsgBuf); + return (jstring) (*env)->NewStringUTF(env, lpDisplayBuf); +} + +JNIEXPORT void JNICALL Java_pipe_Pipes_Print(JNIEnv *env, jclass className, jstring lpMsgBuf) +{ + const jbyte *str; + str = (*env)->GetStringUTFChars(env, lpMsgBuf, NULL); + if (str == NULL) + return; + printf("Native: %s\n", str); + (*env)->ReleaseStringUTFChars(env, lpMsgBuf, str); + return; +} diff --git a/cpp/pipe/src/pipe.h b/cpp/pipe/src/pipe.h new file mode 100644 index 0000000..4687162 --- /dev/null +++ b/cpp/pipe/src/pipe.h @@ -0,0 +1,109 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class Pipes */ + +#ifndef _Included_pipe +#define _Included_pipe +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: Pipes + * Method: CreateNamedPipe + * Signature: (Ljava/lang/String;IIIIIII)I + */ +JNIEXPORT jint JNICALL Java_pipe_Pipes_CreateNamedPipe + (JNIEnv *, jclass, jstring, jint, jint, jint, jint, jint, jint, jint); + +/* + * Class: Pipes + * Method: ConnectNamedPipe + * Signature: (II)Z + */ +JNIEXPORT jboolean JNICALL Java_pipe_Pipes_ConnectNamedPipe + (JNIEnv *, jclass, jint, jint); + +/* + * Class: Pipes + * Method: GetLastError + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_pipe_Pipes_GetLastError + (JNIEnv *, jclass); + +/* + * Class: Pipes + * Method: CloseHandle + * Signature: (I)Z + */ +JNIEXPORT jboolean JNICALL Java_pipe_Pipes_CloseHandle + (JNIEnv *, jclass, jint); + +/* + * Class: Pipes + * Method: ReadFile + * Signature: (II)[B + */ +JNIEXPORT jbyteArray JNICALL Java_pipe_Pipes_ReadFile + (JNIEnv *, jclass, jint, jint); + +/* + * Class: Pipes + * Method: WriteFile + * Signature: (I[BI)I + */ +JNIEXPORT jint JNICALL Java_pipe_Pipes_WriteFile + (JNIEnv *, jclass, jint, jbyteArray, jint); + +/* + * Class: Pipes + * Method: FlushFileBuffers + * Signature: (I)Z + */ +JNIEXPORT jboolean JNICALL Java_pipe_Pipes_FlushFileBuffers + (JNIEnv *, jclass, jint); + +/* + * Class: Pipes + * Method: DisconnectNamedPipe + * Signature: (I)Z + */ +JNIEXPORT jboolean JNICALL Java_pipe_Pipes_DisconnectNamedPipe + (JNIEnv *, jclass, jint); + +/* + * Class: Pipes + * Method: CreateFile + * Signature: (Ljava/lang/String;IIIIII)I + */ +JNIEXPORT jint JNICALL Java_pipe_Pipes_CreateFile + (JNIEnv *, jclass, jstring, jint, jint, jint, jint, jint, jint); + +/* + * Class: Pipes + * Method: WaitNamedPipe + * Signature: (Ljava/lang/String;I)Z + */ +JNIEXPORT jboolean JNICALL Java_pipe_Pipes_WaitNamedPipe + (JNIEnv *, jclass, jstring, jint); + +/* + * Class: Pipes + * Method: FormatMessage + * Signature: (I)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_pipe_Pipes_FormatMessage + (JNIEnv *, jclass, jint); + +/* + * Class: Pipes + * Method: Print + * Signature: (Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_pipe_Pipes_Print + (JNIEnv *, jclass, jstring); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/.classpath b/java/.classpath similarity index 100% rename from .classpath rename to java/.classpath diff --git a/java/.gitignore b/java/.gitignore new file mode 100644 index 0000000..a4bf388 --- /dev/null +++ b/java/.gitignore @@ -0,0 +1,3 @@ +/bin +/.settings +/sound diff --git a/.project b/java/.project similarity index 100% rename from .project rename to java/.project diff --git a/build.xml b/java/build.xml similarity index 100% rename from build.xml rename to java/build.xml diff --git a/lame.exe b/java/lame.exe similarity index 100% rename from lame.exe rename to java/lame.exe diff --git a/launch4j.xml b/java/launch4j.xml similarity index 100% rename from launch4j.xml rename to java/launch4j.xml diff --git a/lib/commons-cli-1.2.jar b/java/lib/commons-cli-1.2.jar similarity index 100% rename from lib/commons-cli-1.2.jar rename to java/lib/commons-cli-1.2.jar diff --git a/lib/commons-io-2.4.jar b/java/lib/commons-io-2.4.jar similarity index 100% rename from lib/commons-io-2.4.jar rename to java/lib/commons-io-2.4.jar diff --git a/lib/jid3lib-0.5.4.jar b/java/lib/jid3lib-0.5.4.jar similarity index 100% rename from lib/jid3lib-0.5.4.jar rename to java/lib/jid3lib-0.5.4.jar diff --git a/lib/jl1.0.1.jar b/java/lib/jl1.0.1.jar similarity index 100% rename from lib/jl1.0.1.jar rename to java/lib/jl1.0.1.jar diff --git a/lib/ostermillerutils-1.08.01.jar b/java/lib/ostermillerutils-1.08.01.jar similarity index 100% rename from lib/ostermillerutils-1.08.01.jar rename to java/lib/ostermillerutils-1.08.01.jar diff --git a/libgomp-1.dll b/java/libgomp-1.dll similarity index 100% rename from libgomp-1.dll rename to java/libgomp-1.dll diff --git a/libmad.dll b/java/libmad.dll similarity index 100% rename from libmad.dll rename to java/libmad.dll diff --git a/libmp3lame.dll b/java/libmp3lame.dll similarity index 100% rename from libmp3lame.dll rename to java/libmp3lame.dll diff --git a/pipes.dll b/java/pipes.dll similarity index 100% rename from pipes.dll rename to java/pipes.dll diff --git a/play.exe b/java/play.exe similarity index 100% rename from play.exe rename to java/play.exe diff --git a/pthreadgc2.dll b/java/pthreadgc2.dll similarity index 100% rename from pthreadgc2.dll rename to java/pthreadgc2.dll diff --git a/sox.exe b/java/sox.exe similarity index 100% rename from sox.exe rename to java/sox.exe diff --git a/soxi.exe b/java/soxi.exe similarity index 100% rename from soxi.exe rename to java/soxi.exe diff --git a/src/old/Converter.java b/java/src/old/Converter.java similarity index 100% rename from src/old/Converter.java rename to java/src/old/Converter.java diff --git a/src/old/List.java b/java/src/old/List.java similarity index 100% rename from src/old/List.java rename to java/src/old/List.java diff --git a/src/old/Mp3.java b/java/src/old/Mp3.java similarity index 100% rename from src/old/Mp3.java rename to java/src/old/Mp3.java diff --git a/src/old/Utils.java b/java/src/old/Utils.java similarity index 100% rename from src/old/Utils.java rename to java/src/old/Utils.java diff --git a/src/sound/Consumer.java b/java/src/sound/Consumer.java similarity index 100% rename from src/sound/Consumer.java rename to java/src/sound/Consumer.java diff --git a/src/sound/Format.java b/java/src/sound/Format.java similarity index 100% rename from src/sound/Format.java rename to java/src/sound/Format.java diff --git a/src/sound/GreedyInputStream.java b/java/src/sound/GreedyInputStream.java similarity index 100% rename from src/sound/GreedyInputStream.java rename to java/src/sound/GreedyInputStream.java diff --git a/src/sound/Port.java b/java/src/sound/Port.java similarity index 100% rename from src/sound/Port.java rename to java/src/sound/Port.java diff --git a/src/sound/Producer.java b/java/src/sound/Producer.java similarity index 100% rename from src/sound/Producer.java rename to java/src/sound/Producer.java diff --git a/src/sound/Source.java b/java/src/sound/Source.java similarity index 100% rename from src/sound/Source.java rename to java/src/sound/Source.java diff --git a/src/sound/SoxBuilder.java b/java/src/sound/SoxBuilder.java similarity index 100% rename from src/sound/SoxBuilder.java rename to java/src/sound/SoxBuilder.java diff --git a/src/sound/Stream.java b/java/src/sound/Stream.java similarity index 100% rename from src/sound/Stream.java rename to java/src/sound/Stream.java diff --git a/src/sound/Target.java b/java/src/sound/Target.java similarity index 100% rename from src/sound/Target.java rename to java/src/sound/Target.java diff --git a/src/sound/Test.java b/java/src/sound/Test.java similarity index 100% rename from src/sound/Test.java rename to java/src/sound/Test.java diff --git a/src/sound/Tool.java b/java/src/sound/Tool.java similarity index 100% rename from src/sound/Tool.java rename to java/src/sound/Tool.java diff --git a/src/sound/Transducer.java b/java/src/sound/Transducer.java similarity index 100% rename from src/sound/Transducer.java rename to java/src/sound/Transducer.java diff --git a/src/test/SoundAudit.java b/java/src/test/SoundAudit.java similarity index 100% rename from src/test/SoundAudit.java rename to java/src/test/SoundAudit.java diff --git a/src/test/lines/Main.java b/java/src/test/lines/Main.java similarity index 100% rename from src/test/lines/Main.java rename to java/src/test/lines/Main.java diff --git a/src/test/lines/SourceLine.java b/java/src/test/lines/SourceLine.java similarity index 100% rename from src/test/lines/SourceLine.java rename to java/src/test/lines/SourceLine.java diff --git a/src/test/lines/TargetLine.java b/java/src/test/lines/TargetLine.java similarity index 100% rename from src/test/lines/TargetLine.java rename to java/src/test/lines/TargetLine.java diff --git a/stream.bat b/java/stream.bat similarity index 100% rename from stream.bat rename to java/stream.bat diff --git a/stream.exe b/java/stream.exe similarity index 100% rename from stream.exe rename to java/stream.exe diff --git a/stream.jar b/java/stream.jar similarity index 100% rename from stream.jar rename to java/stream.jar diff --git a/java/txt/keuze.txt b/java/txt/keuze.txt new file mode 100644 index 0000000..7e9581d --- /dev/null +++ b/java/txt/keuze.txt @@ -0,0 +1,13 @@ +from pcm: + +-r -s [--unsigned] [--big-endian] + +to mp3: +--cbr -b + + +mp3 to pcm: +--decode + +always: + - - --quiet \ No newline at end of file diff --git a/java/txt/mp3 b/java/txt/mp3 new file mode 100644 index 0000000..daf87ab --- /dev/null +++ b/java/txt/mp3 @@ -0,0 +1,1357 @@ +C:/Users/Rik/Music/Artists/+44/When Your Heart Stops Beating/+44 - 155.mp3 +C:/Users/Rik/Music/Artists/+44/When Your Heart Stops Beating/+44 - Baby Come On.mp3 +C:/Users/Rik/Music/Artists/+44/When Your Heart Stops Beating/+44 - Chapter 13.mp3 +C:/Users/Rik/Music/Artists/+44/When Your Heart Stops Beating/+44 - Cliff Diving.mp3 +C:/Users/Rik/Music/Artists/+44/When Your Heart Stops Beating/+44 - Interlude.mp3 +C:/Users/Rik/Music/Artists/+44/When Your Heart Stops Beating/+44 - Lillian.mp3 +C:/Users/Rik/Music/Artists/+44/When Your Heart Stops Beating/+44 - Little Death.mp3 +C:/Users/Rik/Music/Artists/+44/When Your Heart Stops Beating/+44 - Lycanthrope.mp3 +C:/Users/Rik/Music/Artists/+44/When Your Heart Stops Beating/+44 - Make You Smile.mp3 +C:/Users/Rik/Music/Artists/+44/When Your Heart Stops Beating/+44 - No, It Isn't.mp3 +C:/Users/Rik/Music/Artists/+44/When Your Heart Stops Beating/+44 - Weatherman.mp3 +C:/Users/Rik/Music/Artists/+44/When Your Heart Stops Beating/+44 - When Your Heart Stops Beating.mp3 +C:/Users/Rik/Music/Artists/10 Years Feeding/Feeding the Wolves/10 Years - Chasing the Rapture.mp3 +C:/Users/Rik/Music/Artists/10 Years Feeding/Feeding the Wolves/10 Years - Dead In the Water.mp3 +C:/Users/Rik/Music/Artists/10 Years Feeding/Feeding the Wolves/10 Years - Fade Into the Dream.mp3 +C:/Users/Rik/Music/Artists/10 Years Feeding/Feeding the Wolves/10 Years - Fix Me.mp3 +C:/Users/Rik/Music/Artists/10 Years Feeding/Feeding the Wolves/10 Years - Now Is the Time.mp3 +C:/Users/Rik/Music/Artists/10 Years Feeding/Feeding the Wolves/10 Years - One More Day.mp3 +C:/Users/Rik/Music/Artists/10 Years Feeding/Feeding the Wolves/10 Years - The Wicked Ones.mp3 +C:/Users/Rik/Music/Artists/10 Years Feeding/Feeding the Wolves/10 Years - Waking Up the Ghost.mp3 +C:/Users/Rik/Music/Artists/30 Seconds To Mars/A Beautiful Lie/30 Seconds to Mars - A Beautiful Lie.mp3 +C:/Users/Rik/Music/Artists/30 Seconds To Mars/A Beautiful Lie/30 Seconds to Mars - Attack.mp3 +C:/Users/Rik/Music/Artists/30 Seconds To Mars/A Beautiful Lie/30 Seconds to Mars - Battle of One.mp3 +C:/Users/Rik/Music/Artists/30 Seconds To Mars/A Beautiful Lie/30 Seconds to Mars - From Yesterday.mp3 +C:/Users/Rik/Music/Artists/30 Seconds To Mars/A Beautiful Lie/30 Seconds to Mars - R-Evolve.mp3 +C:/Users/Rik/Music/Artists/30 Seconds To Mars/A Beautiful Lie/30 Seconds to Mars - Savior.mp3 +C:/Users/Rik/Music/Artists/30 Seconds To Mars/A Beautiful Lie/30 Seconds to Mars - The Fantasy.mp3 +C:/Users/Rik/Music/Artists/30 Seconds To Mars/A Beautiful Lie/30 Seconds to Mars - Was It a Dream.mp3 +C:/Users/Rik/Music/Artists/30 Seconds To Mars/This Is War/30 Seconds to Mars - A Call to Arms.mp3 +C:/Users/Rik/Music/Artists/30 Seconds To Mars/This Is War/30 Seconds to Mars - Closer to the Edge.mp3 +C:/Users/Rik/Music/Artists/30 Seconds To Mars/This Is War/30 Seconds to Mars - Equinox.mp3 +C:/Users/Rik/Music/Artists/30 Seconds To Mars/This Is War/30 Seconds to Mars - Escape.mp3 +C:/Users/Rik/Music/Artists/30 Seconds To Mars/This Is War/30 Seconds to Mars - Hurricane.mp3 +C:/Users/Rik/Music/Artists/30 Seconds To Mars/This Is War/30 Seconds to Mars - Kings and Queens.mp3 +C:/Users/Rik/Music/Artists/30 Seconds To Mars/This Is War/30 Seconds to Mars - Night of the Hunter (Flood Remix).mp3 +C:/Users/Rik/Music/Artists/30 Seconds To Mars/This Is War/30 Seconds to Mars - Night of the Hunter.mp3 +C:/Users/Rik/Music/Artists/30 Seconds To Mars/This Is War/30 Seconds to Mars - Search & Destroy.mp3 +C:/Users/Rik/Music/Artists/30 Seconds To Mars/This Is War/30 Seconds to Mars - This Is War.mp3 +C:/Users/Rik/Music/Artists/All Time Low/Nothing Personal/All Time Low - A Party Song (The Walk of Shame).mp3 +C:/Users/Rik/Music/Artists/All Time Low/Nothing Personal/All Time Low - Break Your Little Heart.mp3 +C:/Users/Rik/Music/Artists/All Time Low/Nothing Personal/All Time Low - Damned If I Do Ya (Damned If I Don't).mp3 +C:/Users/Rik/Music/Artists/All Time Low/Nothing Personal/All Time Low - Hello Brooklyn.mp3 +C:/Users/Rik/Music/Artists/All Time Low/Nothing Personal/All Time Low - Keep the Change, You Filthy Animal.mp3 +C:/Users/Rik/Music/Artists/All Time Low/Nothing Personal/All Time Low - Lost In Stereo.mp3 +C:/Users/Rik/Music/Artists/All Time Low/Nothing Personal/All Time Low - Sick Little Games.mp3 +C:/Users/Rik/Music/Artists/All Time Low/Nothing Personal/All Time Low - Stella.mp3 +C:/Users/Rik/Music/Artists/All Time Low/Nothing Personal/All Time Low - Therapy.mp3 +C:/Users/Rik/Music/Artists/All Time Low/Nothing Personal/All Time Low - Too Much.mp3 +C:/Users/Rik/Music/Artists/All Time Low/Nothing Personal/All Time Low - Walls.mp3 +C:/Users/Rik/Music/Artists/All Time Low/Nothing Personal/All Time Low - Weightless.mp3 +C:/Users/Rik/Music/Artists/Anberlin/Dark Is The Way, Light Is A Place/Anberlin - Art of War.mp3 +C:/Users/Rik/Music/Artists/Anberlin/Dark Is The Way, Light Is A Place/Anberlin - Closer.mp3 +C:/Users/Rik/Music/Artists/Anberlin/Dark Is The Way, Light Is A Place/Anberlin - Depraved.mp3 +C:/Users/Rik/Music/Artists/Anberlin/Dark Is The Way, Light Is A Place/Anberlin - Down.mp3 +C:/Users/Rik/Music/Artists/Anberlin/Dark Is The Way, Light Is A Place/Anberlin - Impossible.mp3 +C:/Users/Rik/Music/Artists/Anberlin/Dark Is The Way, Light Is A Place/Anberlin - Pray Tell.mp3 +C:/Users/Rik/Music/Artists/Anberlin/Dark Is The Way, Light Is A Place/Anberlin - Take Me (As You Found Me).mp3 +C:/Users/Rik/Music/Artists/Anberlin/Dark Is The Way, Light Is A Place/Anberlin - To the Wolves.mp3 +C:/Users/Rik/Music/Artists/Anberlin/Dark Is The Way, Light Is A Place/Anberlin - We Owe This to Ourselves.mp3 +C:/Users/Rik/Music/Artists/Anberlin/Dark Is The Way, Light Is A Place/Anberlin - You Belong Here.mp3 +C:/Users/Rik/Music/Artists/Angels & Airwaves/Love/Angels & Airwaves - Clever Love.mp3 +C:/Users/Rik/Music/Artists/Angels & Airwaves/Love/Angels & Airwaves - Epic Holiday.mp3 +C:/Users/Rik/Music/Artists/Angels & Airwaves/Love/Angels & Airwaves - Et Ducit Mundum Per Luce.mp3 +C:/Users/Rik/Music/Artists/Angels & Airwaves/Love/Angels & Airwaves - Hallucinations.mp3 +C:/Users/Rik/Music/Artists/Angels & Airwaves/Love/Angels & Airwaves - Letters to God, Part Ii.mp3 +C:/Users/Rik/Music/Artists/Angels & Airwaves/Love/Angels & Airwaves - Shove.mp3 +C:/Users/Rik/Music/Artists/Angels & Airwaves/Love/Angels & Airwaves - Some Origins of Fire.mp3 +C:/Users/Rik/Music/Artists/Angels & Airwaves/Love/Angels & Airwaves - Soul Survivor (...2012).mp3 +C:/Users/Rik/Music/Artists/Angels & Airwaves/Love/Angels & Airwaves - The Flight of Apollo.mp3 +C:/Users/Rik/Music/Artists/Angels & Airwaves/Love/Angels & Airwaves - The Moon-Atomic (...Fragments and Fictions).mp3 +C:/Users/Rik/Music/Artists/Angels & Airwaves/Love/Angels & Airwaves - Young London.mp3 +C:/Users/Rik/Music/Artists/Arcade Fire/The Suburbs/Arcade Fire - City With No Children.mp3 +C:/Users/Rik/Music/Artists/Arcade Fire/The Suburbs/Arcade Fire - Empty Room.mp3 +C:/Users/Rik/Music/Artists/Arcade Fire/The Suburbs/Arcade Fire - Half Light Ii (No Celebration).mp3 +C:/Users/Rik/Music/Artists/Arcade Fire/The Suburbs/Arcade Fire - Modern Man.mp3 +C:/Users/Rik/Music/Artists/Arcade Fire/The Suburbs/Arcade Fire - Month of May.mp3 +C:/Users/Rik/Music/Artists/Arcade Fire/The Suburbs/Arcade Fire - Suburban War.mp3 +C:/Users/Rik/Music/Artists/Blink-182/Greatest Hits/Blink-182 - Adam's Song.mp3 +C:/Users/Rik/Music/Artists/Blink-182/Greatest Hits/Blink-182 - All the Small Things.mp3 +C:/Users/Rik/Music/Artists/Blink-182/Greatest Hits/Blink-182 - Always.mp3 +C:/Users/Rik/Music/Artists/Blink-182/Greatest Hits/Blink-182 - Another Girl Another Planet.mp3 +C:/Users/Rik/Music/Artists/Blink-182/Greatest Hits/Blink-182 - Carousel.mp3 +C:/Users/Rik/Music/Artists/Blink-182/Greatest Hits/Blink-182 - Dammit.mp3 +C:/Users/Rik/Music/Artists/Blink-182/Greatest Hits/Blink-182 - Down.mp3 +C:/Users/Rik/Music/Artists/Blink-182/Greatest Hits/Blink-182 - Feelin' This.mp3 +C:/Users/Rik/Music/Artists/Blink-182/Greatest Hits/Blink-182 - First Date.mp3 +C:/Users/Rik/Music/Artists/Blink-182/Greatest Hits/Blink-182 - Josie.mp3 +C:/Users/Rik/Music/Artists/Blink-182/Greatest Hits/Blink-182 - M&m's.mp3 +C:/Users/Rik/Music/Artists/Blink-182/Greatest Hits/Blink-182 - Man Overboard (Live).mp3 +C:/Users/Rik/Music/Artists/Blink-182/Greatest Hits/Blink-182 - Miss You.mp3 +C:/Users/Rik/Music/Artists/Blink-182/Greatest Hits/Blink-182 - Not Now.mp3 +C:/Users/Rik/Music/Artists/Blink-182/Greatest Hits/Blink-182 - Rock Show.mp3 +C:/Users/Rik/Music/Artists/Blink-182/Greatest Hits/Blink-182 - Stay Together For the Kids.mp3 +C:/Users/Rik/Music/Artists/Blink-182/Greatest Hits/Blink-182 - What's My Age Again.mp3 +C:/Users/Rik/Music/Artists/Coldplay/Coldplay - Clocks.mp3 +C:/Users/Rik/Music/Artists/Coldplay/Coldplay - In My Place.mp3 +C:/Users/Rik/Music/Artists/Coldplay/Coldplay - Life In Technicolor Ii.mp3 +C:/Users/Rik/Music/Artists/Coldplay/Coldplay - Speed of Sound.mp3 +C:/Users/Rik/Music/Artists/Coldplay/Coldplay - Talk.mp3 +C:/Users/Rik/Music/Artists/Coldplay/Viva la Vida or Death and All His Friends/Coldplay - Life In Technicolor.mp3 +C:/Users/Rik/Music/Artists/Coldplay/Viva la Vida or Death and All His Friends/Coldplay - Lost!.mp3 +C:/Users/Rik/Music/Artists/Coldplay/Viva la Vida or Death and All His Friends/Coldplay - Lovers In Japan Reign of Love.mp3 +C:/Users/Rik/Music/Artists/Coldplay/Viva la Vida or Death and All His Friends/Coldplay - Viva La Vida.mp3 +C:/Users/Rik/Music/Artists/Counting Crows/Counting Crows - Accidentally In Love.mp3 +C:/Users/Rik/Music/Artists/Counting Crows/Films About Ghosts - The Best Of/Counting Crows - American Girls.mp3 +C:/Users/Rik/Music/Artists/Counting Crows/Films About Ghosts - The Best Of/Counting Crows - Angels of the Silences.mp3 +C:/Users/Rik/Music/Artists/Counting Crows/Films About Ghosts - The Best Of/Counting Crows - Big Yellow Taxi.mp3 +C:/Users/Rik/Music/Artists/Counting Crows/Films About Ghosts - The Best Of/Counting Crows - Einstein On the Beach (For An Eggman).mp3 +C:/Users/Rik/Music/Artists/Counting Crows/Films About Ghosts - The Best Of/Counting Crows - Friend of the Devil.mp3 +C:/Users/Rik/Music/Artists/Counting Crows/Films About Ghosts - The Best Of/Counting Crows - Hanginaround.mp3 +C:/Users/Rik/Music/Artists/Counting Crows/Films About Ghosts - The Best Of/Counting Crows - Mr. Jones.mp3 +C:/Users/Rik/Music/Artists/Counting Crows/Films About Ghosts - The Best Of/Counting Crows - Mrs. Potter's Lullaby.mp3 +C:/Users/Rik/Music/Artists/Counting Crows/Films About Ghosts - The Best Of/Counting Crows - Omaha.mp3 +C:/Users/Rik/Music/Artists/Counting Crows/Films About Ghosts - The Best Of/Counting Crows - Rain King.mp3 +C:/Users/Rik/Music/Artists/Counting Crows/Films About Ghosts - The Best Of/Counting Crows - Recovering the Satellites.mp3 +C:/Users/Rik/Music/Artists/Counting Crows/Films About Ghosts - The Best Of/Counting Crows - She Don't Want Nobody Near.mp3 +C:/Users/Rik/Music/Artists/Destine/Lightspeed/Destine - Am I So Blind.mp3 +C:/Users/Rik/Music/Artists/Destine/Lightspeed/Destine - Burn.mp3 +C:/Users/Rik/Music/Artists/Destine/Lightspeed/Destine - California Summer.mp3 +C:/Users/Rik/Music/Artists/Destine/Lightspeed/Destine - Everything In Me.mp3 +C:/Users/Rik/Music/Artists/Destine/Lightspeed/Destine - Forget About Me.mp3 +C:/Users/Rik/Music/Artists/Destine/Lightspeed/Destine - In the End.mp3 +C:/Users/Rik/Music/Artists/Destine/Lightspeed/Destine - In Your Arms.mp3 +C:/Users/Rik/Music/Artists/Destine/Lightspeed/Destine - Sinking Sand.mp3 +C:/Users/Rik/Music/Artists/Destine/Lightspeed/Destine - Spiders.mp3 +C:/Users/Rik/Music/Artists/Destine/Lightspeed/Destine - Stars.mp3 +C:/Users/Rik/Music/Artists/Destine/Lightspeed/Destine - Wake Me.mp3 +C:/Users/Rik/Music/Artists/Destine/Lightspeed/Destine - Where Are You Now.mp3 +C:/Users/Rik/Music/Artists/Di-Rect/Di-Rect - Hungry For Love.mp3 +C:/Users/Rik/Music/Artists/Di-Rect/Di-Rect - She.mp3 +C:/Users/Rik/Music/Artists/Di-Rect/Di-Rect/Di-Rect - A Good Thing.mp3 +C:/Users/Rik/Music/Artists/Di-Rect/Di-Rect/Di-Rect - A Whole New Era.mp3 +C:/Users/Rik/Music/Artists/Di-Rect/Di-Rect/Di-Rect - Break Us In Two.mp3 +C:/Users/Rik/Music/Artists/Di-Rect/Di-Rect/Di-Rect - Bring Down Tomorrow.mp3 +C:/Users/Rik/Music/Artists/Di-Rect/Di-Rect/Di-Rect - Don't Look Back.mp3 +C:/Users/Rik/Music/Artists/Di-Rect/Di-Rect/Di-Rect - I Juct Can't Stand.mp3 +C:/Users/Rik/Music/Artists/Di-Rect/Di-Rect/Di-Rect - It Feels.mp3 +C:/Users/Rik/Music/Artists/Di-Rect/Di-Rect/Di-Rect - Johny.mp3 +C:/Users/Rik/Music/Artists/Di-Rect/Di-Rect/Di-Rect - Lucky.mp3 +C:/Users/Rik/Music/Artists/Di-Rect/Di-Rect/Di-Rect - One Step Closer.mp3 +C:/Users/Rik/Music/Artists/Di-Rect/Di-Rect/Di-Rect - Over and Over.mp3 +C:/Users/Rik/Music/Artists/Di-Rect/Di-Rect/Di-Rect - Someday.mp3 +C:/Users/Rik/Music/Artists/Dropout Year/Best Friends For Never/Dropout Year - A Coming of Age Story.mp3 +C:/Users/Rik/Music/Artists/Dropout Year/Best Friends For Never/Dropout Year - As You Wish.mp3 +C:/Users/Rik/Music/Artists/Dropout Year/Best Friends For Never/Dropout Year - Best Friends For Never.mp3 +C:/Users/Rik/Music/Artists/Dropout Year/Best Friends For Never/Dropout Year - Biggest Fan.mp3 +C:/Users/Rik/Music/Artists/Dropout Year/Best Friends For Never/Dropout Year - Confetti.mp3 +C:/Users/Rik/Music/Artists/Dropout Year/Best Friends For Never/Dropout Year - From Across the Room.mp3 +C:/Users/Rik/Music/Artists/Dropout Year/Best Friends For Never/Dropout Year - It Wasn't Over, It Still Isn't Over.mp3 +C:/Users/Rik/Music/Artists/Fall Out Boy/Folie A Deux/Fall Out Boy - (Coffee's For Closers).mp3 +C:/Users/Rik/Music/Artists/Fall Out Boy/Folie A Deux/Fall Out Boy - 20 Dollar Nose Bleed.mp3 +C:/Users/Rik/Music/Artists/Fall Out Boy/Folie A Deux/Fall Out Boy - 27.mp3 +C:/Users/Rik/Music/Artists/Fall Out Boy/Folie A Deux/Fall Out Boy - America's Suitehearts.mp3 +C:/Users/Rik/Music/Artists/Fall Out Boy/Folie A Deux/Fall Out Boy - Disloyal Order of Water Buffaloes.mp3 +C:/Users/Rik/Music/Artists/Fall Out Boy/Folie A Deux/Fall Out Boy - Headfirst Slide Into Coopestown On a Bad Bet.mp3 +C:/Users/Rik/Music/Artists/Fall Out Boy/Folie A Deux/Fall Out Boy - I Don't Care.mp3 +C:/Users/Rik/Music/Artists/Fall Out Boy/Folie A Deux/Fall Out Boy - She's My Winona.mp3 +C:/Users/Rik/Music/Artists/Fall Out Boy/Folie A Deux/Fall Out Boy - Tiffany Blews.mp3 +C:/Users/Rik/Music/Artists/Fall Out Boy/Folie A Deux/Fall Out Boy - West Coast Smoker.mp3 +C:/Users/Rik/Music/Artists/Fall Out Boy/Folie A Deux/Fall Out Boy - What a Catch, Donnie.mp3 +C:/Users/Rik/Music/Artists/Foo Fighters/Greatest Hits/Foo Fighters - All My Life.mp3 +C:/Users/Rik/Music/Artists/Foo Fighters/Greatest Hits/Foo Fighters - Best of You.mp3 +C:/Users/Rik/Music/Artists/Foo Fighters/Greatest Hits/Foo Fighters - Big Me.mp3 +C:/Users/Rik/Music/Artists/Foo Fighters/Greatest Hits/Foo Fighters - Breakout.mp3 +C:/Users/Rik/Music/Artists/Foo Fighters/Greatest Hits/Foo Fighters - Everlong.mp3 +C:/Users/Rik/Music/Artists/Foo Fighters/Greatest Hits/Foo Fighters - Learn to Fly.mp3 +C:/Users/Rik/Music/Artists/Foo Fighters/Greatest Hits/Foo Fighters - Long Road to Ruin.mp3 +C:/Users/Rik/Music/Artists/Foo Fighters/Greatest Hits/Foo Fighters - Monkey Wrench.mp3 +C:/Users/Rik/Music/Artists/Foo Fighters/Greatest Hits/Foo Fighters - My Hero.mp3 +C:/Users/Rik/Music/Artists/Foo Fighters/Greatest Hits/Foo Fighters - The Pretender.mp3 +C:/Users/Rik/Music/Artists/Foo Fighters/Greatest Hits/Foo Fighters - This Is a Call.mp3 +C:/Users/Rik/Music/Artists/Foo Fighters/Greatest Hits/Foo Fighters - Times Like These.mp3 +C:/Users/Rik/Music/Artists/Foo Fighters/Greatest Hits/Foo Fighters - Wheels.mp3 +C:/Users/Rik/Music/Artists/Foo Fighters/Greatest Hits/Foo Fighters - Word Forward.mp3 +C:/Users/Rik/Music/Artists/Foo Fighters/Wasting Light/Foo Fighters - A Matter of Time.mp3 +C:/Users/Rik/Music/Artists/Foo Fighters/Wasting Light/Foo Fighters - Arlandria.mp3 +C:/Users/Rik/Music/Artists/Foo Fighters/Wasting Light/Foo Fighters - Back & Forth.mp3 +C:/Users/Rik/Music/Artists/Foo Fighters/Wasting Light/Foo Fighters - Bridge Burning.mp3 +C:/Users/Rik/Music/Artists/Foo Fighters/Wasting Light/Foo Fighters - Dear Rosemary.mp3 +C:/Users/Rik/Music/Artists/Foo Fighters/Wasting Light/Foo Fighters - Miss the Misery.mp3 +C:/Users/Rik/Music/Artists/Foo Fighters/Wasting Light/Foo Fighters - Rope.mp3 +C:/Users/Rik/Music/Artists/Foo Fighters/Wasting Light/Foo Fighters - These Days.mp3 +C:/Users/Rik/Music/Artists/Foo Fighters/Wasting Light/Foo Fighters - Walk.mp3 +C:/Users/Rik/Music/Artists/Go Back To The Zoo/Benny Blisto/Go Back to the Zoo - Beam Me Up.mp3 +C:/Users/Rik/Music/Artists/Go Back To The Zoo/Benny Blisto/Go Back to the Zoo - Electric.mp3 +C:/Users/Rik/Music/Artists/Go Back To The Zoo/Benny Blisto/Go Back to the Zoo - Fuck You.mp3 +C:/Users/Rik/Music/Artists/Go Back To The Zoo/Benny Blisto/Go Back to the Zoo - Hey Dj.mp3 +C:/Users/Rik/Music/Artists/Go Back To The Zoo/Benny Blisto/Go Back to the Zoo - I Lov It.mp3 +C:/Users/Rik/Music/Artists/Go Back To The Zoo/Benny Blisto/Go Back to the Zoo - I'm the Night (See You Later).mp3 +C:/Users/Rik/Music/Artists/Go Back To The Zoo/Benny Blisto/Go Back to the Zoo - Nicer.mp3 +C:/Users/Rik/Music/Artists/Go Back To The Zoo/Benny Blisto/Go Back to the Zoo - Oh No (We Stayed).mp3 +C:/Users/Rik/Music/Artists/Go Back To The Zoo/Benny Blisto/Go Back to the Zoo - Sweet World.mp3 +C:/Users/Rik/Music/Artists/Good Charlotte/Cardiology/Good Charlotte - 1979.mp3 +C:/Users/Rik/Music/Artists/Good Charlotte/Cardiology/Good Charlotte - Alive.mp3 +C:/Users/Rik/Music/Artists/Good Charlotte/Cardiology/Good Charlotte - Cardiology.mp3 +C:/Users/Rik/Music/Artists/Good Charlotte/Cardiology/Good Charlotte - Counting the Days.mp3 +C:/Users/Rik/Music/Artists/Good Charlotte/Cardiology/Good Charlotte - Harlow's Song (Can't Dream Without You).mp3 +C:/Users/Rik/Music/Artists/Good Charlotte/Cardiology/Good Charlotte - Interlude (The Fifth Chamber).mp3 +C:/Users/Rik/Music/Artists/Good Charlotte/Cardiology/Good Charlotte - Introduction to Cardiology.mp3 +C:/Users/Rik/Music/Artists/Good Charlotte/Cardiology/Good Charlotte - Last Night.mp3 +C:/Users/Rik/Music/Artists/Good Charlotte/Cardiology/Good Charlotte - Let the Music Play.mp3 +C:/Users/Rik/Music/Artists/Good Charlotte/Cardiology/Good Charlotte - Like It's Her Birthday.mp3 +C:/Users/Rik/Music/Artists/Good Charlotte/Cardiology/Good Charlotte - Right Where I Belong.mp3 +C:/Users/Rik/Music/Artists/Good Charlotte/Cardiology/Good Charlotte - Sex On the Radio.mp3 +C:/Users/Rik/Music/Artists/Good Charlotte/Cardiology/Good Charlotte - Silver Screen Romance.mp3 +C:/Users/Rik/Music/Artists/Good Charlotte/Cardiology/Good Charlotte - Standing Ovation.mp3 +C:/Users/Rik/Music/Artists/Good Charlotte/Cardiology/Good Charlotte - There She Goes.mp3 +C:/Users/Rik/Music/Artists/Green Day/21st Century Breakdown/Green Day - 21 Guns.mp3 +C:/Users/Rik/Music/Artists/Green Day/21st Century Breakdown/Green Day - 21st Century Breakdown.mp3 +C:/Users/Rik/Music/Artists/Green Day/21st Century Breakdown/Green Day - American Eulogy.mp3 +C:/Users/Rik/Music/Artists/Green Day/21st Century Breakdown/Green Day - Before the Lobotomy.mp3 +C:/Users/Rik/Music/Artists/Green Day/21st Century Breakdown/Green Day - Christian's Inferno.mp3 +C:/Users/Rik/Music/Artists/Green Day/21st Century Breakdown/Green Day - East Jesus Nowhere.mp3 +C:/Users/Rik/Music/Artists/Green Day/21st Century Breakdown/Green Day - Horseshoes and Handgrenades.mp3 +C:/Users/Rik/Music/Artists/Green Day/21st Century Breakdown/Green Day - Know Your Enemy.mp3 +C:/Users/Rik/Music/Artists/Green Day/21st Century Breakdown/Green Day - Last Night On Earth.mp3 +C:/Users/Rik/Music/Artists/Green Day/21st Century Breakdown/Green Day - Last of the American Girls.mp3 +C:/Users/Rik/Music/Artists/Green Day/21st Century Breakdown/Green Day - Murder City.mp3 +C:/Users/Rik/Music/Artists/Green Day/21st Century Breakdown/Green Day - Peacemaker.mp3 +C:/Users/Rik/Music/Artists/Green Day/21st Century Breakdown/Green Day - Restless Heart Syndrome.mp3 +C:/Users/Rik/Music/Artists/Green Day/21st Century Breakdown/Green Day - See the Light.mp3 +C:/Users/Rik/Music/Artists/Green Day/21st Century Breakdown/Green Day - The Static Age.mp3 +C:/Users/Rik/Music/Artists/Green Day/21st Century Breakdown/Green Day - Viva La Gloria (Little Girl).mp3 +C:/Users/Rik/Music/Artists/Green Day/American Idiot/Green Day - American Idiot.mp3 +C:/Users/Rik/Music/Artists/Green Day/American Idiot/Green Day - Are We the Waiting.mp3 +C:/Users/Rik/Music/Artists/Green Day/American Idiot/Green Day - Boulevard of Broken Dreams.mp3 +C:/Users/Rik/Music/Artists/Green Day/American Idiot/Green Day - Extraordinary Girl.mp3 +C:/Users/Rik/Music/Artists/Green Day/American Idiot/Green Day - Give Me Novacaine.mp3 +C:/Users/Rik/Music/Artists/Green Day/American Idiot/Green Day - Holiday.mp3 +C:/Users/Rik/Music/Artists/Green Day/American Idiot/Green Day - Homecoming.mp3 +C:/Users/Rik/Music/Artists/Green Day/American Idiot/Green Day - Jesus of Suburbia.mp3 +C:/Users/Rik/Music/Artists/Green Day/American Idiot/Green Day - Letterbomb.mp3 +C:/Users/Rik/Music/Artists/Green Day/American Idiot/Green Day - She's a Rebel.mp3 +C:/Users/Rik/Music/Artists/Green Day/American Idiot/Green Day - St. Jimmy.mp3 +C:/Users/Rik/Music/Artists/Green Day/American Idiot/Green Day - Wake Me Up When September Ends.mp3 +C:/Users/Rik/Music/Artists/Green Day/American Idiot/Green Day - Whatsername.mp3 +C:/Users/Rik/Music/Artists/Green Day/Greatest Hits/Green Day - All the Time.mp3 +C:/Users/Rik/Music/Artists/Green Day/Greatest Hits/Green Day - Armatage Shanks.mp3 +C:/Users/Rik/Music/Artists/Green Day/Greatest Hits/Green Day - Bascet Case.mp3 +C:/Users/Rik/Music/Artists/Green Day/Greatest Hits/Green Day - Brat.mp3 +C:/Users/Rik/Music/Artists/Green Day/Greatest Hits/Green Day - Burnout.mp3 +C:/Users/Rik/Music/Artists/Green Day/Greatest Hits/Green Day - Chump.mp3 +C:/Users/Rik/Music/Artists/Green Day/Greatest Hits/Green Day - Church On Sunday.mp3 +C:/Users/Rik/Music/Artists/Green Day/Greatest Hits/Green Day - Coming Clean.mp3 +C:/Users/Rik/Music/Artists/Green Day/Greatest Hits/Green Day - Desensitized.mp3 +C:/Users/Rik/Music/Artists/Green Day/Greatest Hits/Green Day - Emenius Sleepus.mp3 +C:/Users/Rik/Music/Artists/Green Day/Greatest Hits/Green Day - Fashion Victim.mp3 +C:/Users/Rik/Music/Artists/Green Day/Greatest Hits/Green Day - Geek Stink Breath.mp3 +C:/Users/Rik/Music/Artists/Green Day/Greatest Hits/Green Day - Good Riddance (Time of Your Life).mp3 +C:/Users/Rik/Music/Artists/Green Day/Greatest Hits/Green Day - In the End.mp3 +C:/Users/Rik/Music/Artists/Green Day/Greatest Hits/Green Day - J.A.R. (Jason Andrew Relva).mp3 +C:/Users/Rik/Music/Artists/Green Day/Greatest Hits/Green Day - Jaded.mp3 +C:/Users/Rik/Music/Artists/Green Day/Greatest Hits/Green Day - Maria.mp3 +C:/Users/Rik/Music/Artists/Green Day/Greatest Hits/Green Day - Nice Guys Finish Last.mp3 +C:/Users/Rik/Music/Artists/Green Day/Greatest Hits/Green Day - Poprocks & Coke.mp3 +C:/Users/Rik/Music/Artists/Green Day/Greatest Hits/Green Day - Redundant.mp3 +C:/Users/Rik/Music/Artists/Green Day/Greatest Hits/Green Day - Scumbag.mp3 +C:/Users/Rik/Music/Artists/Green Day/Greatest Hits/Green Day - She.mp3 +C:/Users/Rik/Music/Artists/Green Day/Greatest Hits/Green Day - Stuck With Me.mp3 +C:/Users/Rik/Music/Artists/Green Day/Greatest Hits/Green Day - Suffocate.mp3 +C:/Users/Rik/Music/Artists/Green Day/Greatest Hits/Green Day - The Grouch.mp3 +C:/Users/Rik/Music/Artists/Green Day/Greatest Hits/Green Day - The Saints Are Coming.mp3 +C:/Users/Rik/Music/Artists/Green Day/Greatest Hits/Green Day - Waiting.mp3 +C:/Users/Rik/Music/Artists/Green Day/Greatest Hits/Green Day - Walking Alone.mp3 +C:/Users/Rik/Music/Artists/Green Day/Greatest Hits/Green Day - Walking Contradiction.mp3 +C:/Users/Rik/Music/Artists/Green Day/Greatest Hits/Green Day - Warning.mp3 +C:/Users/Rik/Music/Artists/Green Day/Greatest Hits/Green Day - Welcome to Paradise.mp3 +C:/Users/Rik/Music/Artists/Kaiser Chiefs/Off With Their Heads/Kaiser Chiefs - Addicted to Drugs.mp3 +C:/Users/Rik/Music/Artists/Kaiser Chiefs/Off With Their Heads/Kaiser Chiefs - Always Happens Like That.mp3 +C:/Users/Rik/Music/Artists/Kaiser Chiefs/Off With Their Heads/Kaiser Chiefs - Can't Say What I Mean.mp3 +C:/Users/Rik/Music/Artists/Kaiser Chiefs/Off With Their Heads/Kaiser Chiefs - Good Days Bad Days.mp3 +C:/Users/Rik/Music/Artists/Kaiser Chiefs/Off With Their Heads/Kaiser Chiefs - Half the Truth.mp3 +C:/Users/Rik/Music/Artists/Kaiser Chiefs/Off With Their Heads/Kaiser Chiefs - Like It Too Much.mp3 +C:/Users/Rik/Music/Artists/Kaiser Chiefs/Off With Their Heads/Kaiser Chiefs - Never Miss a Beat.mp3 +C:/Users/Rik/Music/Artists/Kaiser Chiefs/Off With Their Heads/Kaiser Chiefs - Spanish Metal.mp3 +C:/Users/Rik/Music/Artists/Kaiser Chiefs/Off With Their Heads/Kaiser Chiefs - Tomato In the Rain.mp3 +C:/Users/Rik/Music/Artists/Kaiser Chiefs/Off With Their Heads/Kaiser Chiefs - You Want History.mp3 +C:/Users/Rik/Music/Artists/Kaiser Chiefs/Yours Truly, Angry Mob/Kaiser Chiefs - Boxing Champ.mp3 +C:/Users/Rik/Music/Artists/Kaiser Chiefs/Yours Truly, Angry Mob/Kaiser Chiefs - Everything Is Average Nowadays.mp3 +C:/Users/Rik/Music/Artists/Kaiser Chiefs/Yours Truly, Angry Mob/Kaiser Chiefs - Heat Dies Down.mp3 +C:/Users/Rik/Music/Artists/Kaiser Chiefs/Yours Truly, Angry Mob/Kaiser Chiefs - Highroyds.mp3 +C:/Users/Rik/Music/Artists/Kaiser Chiefs/Yours Truly, Angry Mob/Kaiser Chiefs - I Can Do Without You.mp3 +C:/Users/Rik/Music/Artists/Kaiser Chiefs/Yours Truly, Angry Mob/Kaiser Chiefs - Learnt My Lesson Well.mp3 +C:/Users/Rik/Music/Artists/Kaiser Chiefs/Yours Truly, Angry Mob/Kaiser Chiefs - Love's Not a Competition (But I'm Winning).mp3 +C:/Users/Rik/Music/Artists/Kaiser Chiefs/Yours Truly, Angry Mob/Kaiser Chiefs - My Kind of Guy.mp3 +C:/Users/Rik/Music/Artists/Kaiser Chiefs/Yours Truly, Angry Mob/Kaiser Chiefs - Retirement.mp3 +C:/Users/Rik/Music/Artists/Kaiser Chiefs/Yours Truly, Angry Mob/Kaiser Chiefs - Ruby.mp3 +C:/Users/Rik/Music/Artists/Kaiser Chiefs/Yours Truly, Angry Mob/Kaiser Chiefs - Thank You Very Much.mp3 +C:/Users/Rik/Music/Artists/Kaiser Chiefs/Yours Truly, Angry Mob/Kaiser Chiefs - The Angry Mob.mp3 +C:/Users/Rik/Music/Artists/Kaiser Chiefs/Yours Truly, Angry Mob/Kaiser Chiefs - Try Your Best.mp3 +C:/Users/Rik/Music/Artists/Keane/Keane - Everybody's Changing.mp3 +C:/Users/Rik/Music/Artists/Keane/Keane - Is It Any Wonder.mp3 +C:/Users/Rik/Music/Artists/Keane/Keane - Somewhere Only We Know.mp3 +C:/Users/Rik/Music/Artists/Keane/Keane - This Is the Last Time.mp3 +C:/Users/Rik/Music/Artists/Keane/Perfect Symmetry/Keane - Again & Again.mp3 +C:/Users/Rik/Music/Artists/Keane/Perfect Symmetry/Keane - Better Than This.mp3 +C:/Users/Rik/Music/Artists/Keane/Perfect Symmetry/Keane - Black Burning Heart.mp3 +C:/Users/Rik/Music/Artists/Keane/Perfect Symmetry/Keane - Lovers Are Losing.mp3 +C:/Users/Rik/Music/Artists/Keane/Perfect Symmetry/Keane - Perfect Symmetry.mp3 +C:/Users/Rik/Music/Artists/Keane/Perfect Symmetry/Keane - Playing Along.mp3 +C:/Users/Rik/Music/Artists/Keane/Perfect Symmetry/Keane - Pretend That You're Alone.mp3 +C:/Users/Rik/Music/Artists/Keane/Perfect Symmetry/Keane - Spiralling.mp3 +C:/Users/Rik/Music/Artists/Keane/Perfect Symmetry/Keane - You Don't See Me.mp3 +C:/Users/Rik/Music/Artists/Kensington/Borders/Kensington - All That I Know.mp3 +C:/Users/Rik/Music/Artists/Kensington/Borders/Kensington - Franklin Exits.mp3 +C:/Users/Rik/Music/Artists/Kensington/Borders/Kensington - I Was Too Scared.mp3 +C:/Users/Rik/Music/Artists/Kensington/Borders/Kensington - Not As Bright.mp3 +C:/Users/Rik/Music/Artists/Kensington/Borders/Kensington - So Am I.mp3 +C:/Users/Rik/Music/Artists/Kensington/Borders/Kensington - The Heart of It.mp3 +C:/Users/Rik/Music/Artists/Kensington/Borders/Kensington - Thieves and Murderers.mp3 +C:/Users/Rik/Music/Artists/Kensington/Borders/Kensington - Waiting For a Sign.mp3 +C:/Users/Rik/Music/Artists/Kensington/Borders/Kensington - What's Gotten Into Us.mp3 +C:/Users/Rik/Music/Artists/Kensington/Borders/Kensington - When It All Falls Down.mp3 +C:/Users/Rik/Music/Artists/Kensington/Borders/Kensington - Youth.mp3 +C:/Users/Rik/Music/Artists/Kings of Leon/Come Around Sundown/Kings of Leon - Back Down South.mp3 +C:/Users/Rik/Music/Artists/Kings of Leon/Come Around Sundown/Kings of Leon - Beach Side.mp3 +C:/Users/Rik/Music/Artists/Kings of Leon/Come Around Sundown/Kings of Leon - Birthday.mp3 +C:/Users/Rik/Music/Artists/Kings of Leon/Come Around Sundown/Kings of Leon - Mary.mp3 +C:/Users/Rik/Music/Artists/Kings of Leon/Come Around Sundown/Kings of Leon - Mi Amigo.mp3 +C:/Users/Rik/Music/Artists/Kings of Leon/Come Around Sundown/Kings of Leon - No Money.mp3 +C:/Users/Rik/Music/Artists/Kings of Leon/Come Around Sundown/Kings of Leon - Pickup Truck.mp3 +C:/Users/Rik/Music/Artists/Kings of Leon/Come Around Sundown/Kings of Leon - Pony Up.mp3 +C:/Users/Rik/Music/Artists/Kings of Leon/Come Around Sundown/Kings of Leon - Pyro.mp3 +C:/Users/Rik/Music/Artists/Kings of Leon/Come Around Sundown/Kings of Leon - Radioactive.mp3 +C:/Users/Rik/Music/Artists/Kings of Leon/Come Around Sundown/Kings of Leon - The End.mp3 +C:/Users/Rik/Music/Artists/Kings of Leon/Come Around Sundown/Kings of Leon - The Face.mp3 +C:/Users/Rik/Music/Artists/Kings of Leon/Come Around Sundown/Kings of Leon - The Immortals.mp3 +C:/Users/Rik/Music/Artists/Kings of Leon/Only By The Night/Kings of Leon - Be Somebody.mp3 +C:/Users/Rik/Music/Artists/Kings of Leon/Only By The Night/Kings of Leon - Closer.mp3 +C:/Users/Rik/Music/Artists/Kings of Leon/Only By The Night/Kings of Leon - Crawl.mp3 +C:/Users/Rik/Music/Artists/Kings of Leon/Only By The Night/Kings of Leon - I Want You.mp3 +C:/Users/Rik/Music/Artists/Kings of Leon/Only By The Night/Kings of Leon - Manhattan.mp3 +C:/Users/Rik/Music/Artists/Kings of Leon/Only By The Night/Kings of Leon - Notion.mp3 +C:/Users/Rik/Music/Artists/Kings of Leon/Only By The Night/Kings of Leon - Sex On Fire.mp3 +C:/Users/Rik/Music/Artists/Kings of Leon/Only By The Night/Kings of Leon - Use Somebody.mp3 +C:/Users/Rik/Music/Artists/Lifehouse/Smoke & Mirrors/Lifehouse - All In.mp3 +C:/Users/Rik/Music/Artists/Lifehouse/Smoke & Mirrors/Lifehouse - All That I'm Asking For.mp3 +C:/Users/Rik/Music/Artists/Lifehouse/Smoke & Mirrors/Lifehouse - By Your Side.mp3 +C:/Users/Rik/Music/Artists/Lifehouse/Smoke & Mirrors/Lifehouse - Crash and Burn.mp3 +C:/Users/Rik/Music/Artists/Lifehouse/Smoke & Mirrors/Lifehouse - Falling In.mp3 +C:/Users/Rik/Music/Artists/Lifehouse/Smoke & Mirrors/Lifehouse - From Where You Are.mp3 +C:/Users/Rik/Music/Artists/Lifehouse/Smoke & Mirrors/Lifehouse - Had Enough.mp3 +C:/Users/Rik/Music/Artists/Lifehouse/Smoke & Mirrors/Lifehouse - Halfway Gone.mp3 +C:/Users/Rik/Music/Artists/Lifehouse/Smoke & Mirrors/Lifehouse - In Your Skin.mp3 +C:/Users/Rik/Music/Artists/Lifehouse/Smoke & Mirrors/Lifehouse - It Is What It Is.mp3 +C:/Users/Rik/Music/Artists/Lifehouse/Smoke & Mirrors/Lifehouse - Smoke & Mirrors.mp3 +C:/Users/Rik/Music/Artists/Lifehouse/Smoke & Mirrors/Lifehouse - Wrecking Ball.mp3 +C:/Users/Rik/Music/Artists/Lifehouse/Who We Are/Lifehouse - Bridges.mp3 +C:/Users/Rik/Music/Artists/Lifehouse/Who We Are/Lifehouse - Disarray.mp3 +C:/Users/Rik/Music/Artists/Lifehouse/Who We Are/Lifehouse - Easier to Be.mp3 +C:/Users/Rik/Music/Artists/Lifehouse/Who We Are/Lifehouse - First Time.mp3 +C:/Users/Rik/Music/Artists/Lifehouse/Who We Are/Lifehouse - Learn You Inside Out.mp3 +C:/Users/Rik/Music/Artists/Lifehouse/Who We Are/Lifehouse - Make Me Over.mp3 +C:/Users/Rik/Music/Artists/Lifehouse/Who We Are/Lifehouse - Mesmerized.mp3 +C:/Users/Rik/Music/Artists/Lifehouse/Who We Are/Lifehouse - Storm.mp3 +C:/Users/Rik/Music/Artists/Lifehouse/Who We Are/Lifehouse - Whatever It Takes.mp3 +C:/Users/Rik/Music/Artists/Lifehouse/Who We Are/Lifehouse - Who We Are.mp3 +C:/Users/Rik/Music/Artists/Linking Park/Hybrid Theory/Linkin Park - A Place For My Head.mp3 +C:/Users/Rik/Music/Artists/Linking Park/Hybrid Theory/Linkin Park - Crawling.mp3 +C:/Users/Rik/Music/Artists/Linking Park/Hybrid Theory/Linkin Park - Forgotten.mp3 +C:/Users/Rik/Music/Artists/Linking Park/Hybrid Theory/Linkin Park - In the End.mp3 +C:/Users/Rik/Music/Artists/Linking Park/Hybrid Theory/Linkin Park - One Step Closer.mp3 +C:/Users/Rik/Music/Artists/Linking Park/Hybrid Theory/Linkin Park - Papercut.mp3 +C:/Users/Rik/Music/Artists/Linking Park/Hybrid Theory/Linkin Park - Points of Authority.mp3 +C:/Users/Rik/Music/Artists/Linking Park/Hybrid Theory/Linkin Park - Pushing Me Away.mp3 +C:/Users/Rik/Music/Artists/Linking Park/Hybrid Theory/Linkin Park - Runaway.mp3 +C:/Users/Rik/Music/Artists/Linking Park/Hybrid Theory/Linkin Park - With You.mp3 +C:/Users/Rik/Music/Artists/Lostprophets/Liberation Transmission/Lostprophets - 4am Forever.mp3 +C:/Users/Rik/Music/Artists/Lostprophets/Liberation Transmission/Lostprophets - A Town Called Hypocrisy.mp3 +C:/Users/Rik/Music/Artists/Lostprophets/Liberation Transmission/Lostprophets - Always All Ways (Apologies, Glances and Messed Up Chances).mp3 +C:/Users/Rik/Music/Artists/Lostprophets/Liberation Transmission/Lostprophets - Broken Hearts, Torn Up Letters and the Story of a Lonely Girl.mp3 +C:/Users/Rik/Music/Artists/Lostprophets/Liberation Transmission/Lostprophets - Can't Catch Tomorrow (Good Shoes Won't Save You This Time).mp3 +C:/Users/Rik/Music/Artists/Lostprophets/Liberation Transmission/Lostprophets - Can't Stop, Gotta Date With Hate.mp3 +C:/Users/Rik/Music/Artists/Lostprophets/Liberation Transmission/Lostprophets - Everybody's Screaming !!!.mp3 +C:/Users/Rik/Music/Artists/Lostprophets/Liberation Transmission/Lostprophets - Everyday Combat.mp3 +C:/Users/Rik/Music/Artists/Lostprophets/Liberation Transmission/Lostprophets - For All These Times Son, For All These Times.mp3 +C:/Users/Rik/Music/Artists/Lostprophets/Liberation Transmission/Lostprophets - Heaven For the Weather, Hell For the Company.mp3 +C:/Users/Rik/Music/Artists/Lostprophets/Liberation Transmission/Lostprophets - Rooftops (A Liberation Broadcast).mp3 +C:/Users/Rik/Music/Artists/Lostprophets/Liberation Transmission/Lostprophets - The New Transmission.mp3 +C:/Users/Rik/Music/Artists/Matchbook Romance/Voices/Matchbook Romance - Goody, Like Two Shoes.mp3 +C:/Users/Rik/Music/Artists/Matchbook Romance/Voices/Matchbook Romance - Monsters.mp3 +C:/Users/Rik/Music/Artists/Matchbook Romance/Voices/Matchbook Romance - My Mannequin Can Dance.mp3 +C:/Users/Rik/Music/Artists/Matchbook Romance/Voices/Matchbook Romance - Portrait.mp3 +C:/Users/Rik/Music/Artists/Matchbook Romance/Voices/Matchbook Romance - Singing Bridges (We All Fall).mp3 +C:/Users/Rik/Music/Artists/Matchbook Romance/Voices/Matchbook Romance - Surrender.mp3 +C:/Users/Rik/Music/Artists/Matchbook Romance/Voices/Matchbook Romance - What a Sight.mp3 +C:/Users/Rik/Music/Artists/Neon Trees/Habits/Neon Trees - 1983.mp3 +C:/Users/Rik/Music/Artists/Neon Trees/Habits/Neon Trees - Animal.mp3 +C:/Users/Rik/Music/Artists/Neon Trees/Habits/Neon Trees - In the Next Room.mp3 +C:/Users/Rik/Music/Artists/Neon Trees/Habits/Neon Trees - Sins of My Youth.mp3 +C:/Users/Rik/Music/Artists/Neon Trees/Habits/Neon Trees - Your Surrender.mp3 +C:/Users/Rik/Music/Artists/Nickelback/Dark Horse/Nickelback - Gotta Be Somebody.mp3 +C:/Users/Rik/Music/Artists/Nickelback/Dark Horse/Nickelback - I'd Come For You.mp3 +C:/Users/Rik/Music/Artists/Nickelback/Dark Horse/Nickelback - If Today Was Your Last Day.mp3 +C:/Users/Rik/Music/Artists/Nickelback/Dark Horse/Nickelback - Just to Get High.mp3 +C:/Users/Rik/Music/Artists/Nickelback/Dark Horse/Nickelback - Never Gonna Be Alone.mp3 +C:/Users/Rik/Music/Artists/Nickelback/Dark Horse/Nickelback - This Afternoon.mp3 +C:/Users/Rik/Music/Artists/Nickelback/Nickelback - How You Remind Me.mp3 +C:/Users/Rik/Music/Artists/Nickelback/Nickelback - Photograph.mp3 +C:/Users/Rik/Music/Artists/OneRepublic/Waking Up/Onerepublic - All the Right Moves.mp3 +C:/Users/Rik/Music/Artists/OneRepublic/Waking Up/Onerepublic - Fear.mp3 +C:/Users/Rik/Music/Artists/OneRepublic/Waking Up/Onerepublic - Good Life.mp3 +C:/Users/Rik/Music/Artists/OneRepublic/Waking Up/Onerepublic - Secrets.mp3 +C:/Users/Rik/Music/Artists/Plain White T's/All That We Needed/Plain White T's - All That We Needed.mp3 +C:/Users/Rik/Music/Artists/Plain White T's/All That We Needed/Plain White T's - Anything.mp3 +C:/Users/Rik/Music/Artists/Plain White T's/All That We Needed/Plain White T's - Breakdown.mp3 +C:/Users/Rik/Music/Artists/Plain White T's/All That We Needed/Plain White T's - Faster.mp3 +C:/Users/Rik/Music/Artists/Plain White T's/All That We Needed/Plain White T's - Last Call.mp3 +C:/Users/Rik/Music/Artists/Plain White T's/All That We Needed/Plain White T's - Lazy Day Afternoon.mp3 +C:/Users/Rik/Music/Artists/Plain White T's/All That We Needed/Plain White T's - My Only One.mp3 +C:/Users/Rik/Music/Artists/Plain White T's/All That We Needed/Plain White T's - Revenge.mp3 +C:/Users/Rik/Music/Artists/Plain White T's/All That We Needed/Plain White T's - Sad Story.mp3 +C:/Users/Rik/Music/Artists/Plain White T's/All That We Needed/Plain White T's - Sing My Best.mp3 +C:/Users/Rik/Music/Artists/Plain White T's/All That We Needed/Plain White T's - Take Me Away.mp3 +C:/Users/Rik/Music/Artists/Plain White T's/All That We Needed/Plain White T's - What More Do You Want.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/Greatest Hits/Red Hot Chili Peppers - Breaking the Girl.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/Greatest Hits/Red Hot Chili Peppers - By the Way.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/Greatest Hits/Red Hot Chili Peppers - Californication.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/Greatest Hits/Red Hot Chili Peppers - Fortune Faded.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/Greatest Hits/Red Hot Chili Peppers - Give It Away.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/Greatest Hits/Red Hot Chili Peppers - Higher Ground.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/Greatest Hits/Red Hot Chili Peppers - My Friends.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/Greatest Hits/Red Hot Chili Peppers - Otherside.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/Greatest Hits/Red Hot Chili Peppers - Parallel Universe.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/Greatest Hits/Red Hot Chili Peppers - Save the Population.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/Greatest Hits/Red Hot Chili Peppers - Scar Tissue.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/Greatest Hits/Red Hot Chili Peppers - Soul to Squeeze.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/Greatest Hits/Red Hot Chili Peppers - Under the Bridge.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/Greatest Hits/Red Hot Chili Peppers - Universally Speaking.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/Stadium Arcadium/Red Hot Chili Peppers - Animal Bar.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/Stadium Arcadium/Red Hot Chili Peppers - Charlie.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/Stadium Arcadium/Red Hot Chili Peppers - C'mon Girl.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/Stadium Arcadium/Red Hot Chili Peppers - Dani California.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/Stadium Arcadium/Red Hot Chili Peppers - Death of a Martian.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/Stadium Arcadium/Red Hot Chili Peppers - Desecration Smile.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/Stadium Arcadium/Red Hot Chili Peppers - Especially In Michigan.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/Stadium Arcadium/Red Hot Chili Peppers - Hard to Concentrate.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/Stadium Arcadium/Red Hot Chili Peppers - Hey.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/Stadium Arcadium/Red Hot Chili Peppers - If.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/Stadium Arcadium/Red Hot Chili Peppers - Make You Feel Better.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/Stadium Arcadium/Red Hot Chili Peppers - She Looks to Me.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/Stadium Arcadium/Red Hot Chili Peppers - She's Only 18.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/Stadium Arcadium/Red Hot Chili Peppers - Slow Cheetah.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/Stadium Arcadium/Red Hot Chili Peppers - Snow (Hey Oh).mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/Stadium Arcadium/Red Hot Chili Peppers - So Much I.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/Stadium Arcadium/Red Hot Chili Peppers - Stadium Arcadium.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/Stadium Arcadium/Red Hot Chili Peppers - Storm In a Teacup.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/Stadium Arcadium/Red Hot Chili Peppers - Strip My Mind.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/Stadium Arcadium/Red Hot Chili Peppers - Tell Me Baby.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/Stadium Arcadium/Red Hot Chili Peppers - Torture Me.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/Stadium Arcadium/Red Hot Chili Peppers - Turn It Again.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/Stadium Arcadium/Red Hot Chili Peppers - Warlocks.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/Stadium Arcadium/Red Hot Chili Peppers - We Believe.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/Stadium Arcadium/Red Hot Chili Peppers - Wet Sand.mp3 +C:/Users/Rik/Music/Artists/Rooney/Calling The World/Rooney - All In Your Head.mp3 +C:/Users/Rik/Music/Artists/Rooney/Calling The World/Rooney - Are You Afraid.mp3 +C:/Users/Rik/Music/Artists/Rooney/Calling The World/Rooney - Believe In Me.mp3 +C:/Users/Rik/Music/Artists/Rooney/Calling The World/Rooney - Calling the World.mp3 +C:/Users/Rik/Music/Artists/Rooney/Calling The World/Rooney - Don't Come Around Again.mp3 +C:/Users/Rik/Music/Artists/Rooney/Calling The World/Rooney - I Should've Been After You.mp3 +C:/Users/Rik/Music/Artists/Rooney/Calling The World/Rooney - Love Me Or Leave Me.mp3 +C:/Users/Rik/Music/Artists/Rooney/Calling The World/Rooney - Paralyzed.mp3 +C:/Users/Rik/Music/Artists/Rooney/Calling The World/Rooney - What For.mp3 +C:/Users/Rik/Music/Artists/Savage Garden/Savage Garden/Savage Garden - A Thousand Words.mp3 +C:/Users/Rik/Music/Artists/Savage Garden/Savage Garden/Savage Garden - Break Me Shake Me.mp3 +C:/Users/Rik/Music/Artists/Savage Garden/Savage Garden/Savage Garden - Carry On Dancing.mp3 +C:/Users/Rik/Music/Artists/Savage Garden/Savage Garden/Savage Garden - I Want You.mp3 +C:/Users/Rik/Music/Artists/Savage Garden/Savage Garden/Savage Garden - To the Moon and Back.mp3 +C:/Users/Rik/Music/Artists/Savage Garden/Savage Garden/Savage Garden - Truly Madly Deeply.mp3 +C:/Users/Rik/Music/Artists/Savage Garden/Savage Garden/Savage Garden - Violet.mp3 +C:/Users/Rik/Music/Artists/Simple Plan/Simple Plan/Simple Plan - Generation.mp3 +C:/Users/Rik/Music/Artists/Simple Plan/Simple Plan/Simple Plan - I Can Wait Forever.mp3 +C:/Users/Rik/Music/Artists/Simple Plan/Simple Plan/Simple Plan - No Love.mp3 +C:/Users/Rik/Music/Artists/Simple Plan/Simple Plan/Simple Plan - Running Out of Time.mp3 +C:/Users/Rik/Music/Artists/Simple Plan/Simple Plan/Simple Plan - Save You.mp3 +C:/Users/Rik/Music/Artists/Simple Plan/Simple Plan/Simple Plan - Take My Hand.mp3 +C:/Users/Rik/Music/Artists/Simple Plan/Simple Plan/Simple Plan - The End.mp3 +C:/Users/Rik/Music/Artists/Simple Plan/Simple Plan/Simple Plan - Time to Say Goodbye.mp3 +C:/Users/Rik/Music/Artists/Simple Plan/Simple Plan/Simple Plan - What If.mp3 +C:/Users/Rik/Music/Artists/Simple Plan/Simple Plan/Simple Plan - When I'm Gone (Acoustic).mp3 +C:/Users/Rik/Music/Artists/Simple Plan/Simple Plan/Simple Plan - When I'm Gone.mp3 +C:/Users/Rik/Music/Artists/Simple Plan/Simple Plan/Simple Plan - Your Love Is a Lie.mp3 +C:/Users/Rik/Music/Artists/Snow Patrol/A Hundred Million Suns/Snow Patrol - Crack the Shutters.mp3 +C:/Users/Rik/Music/Artists/Snow Patrol/A Hundred Million Suns/Snow Patrol - Disaster Button.mp3 +C:/Users/Rik/Music/Artists/Snow Patrol/A Hundred Million Suns/Snow Patrol - Engines.mp3 +C:/Users/Rik/Music/Artists/Snow Patrol/A Hundred Million Suns/Snow Patrol - If There's a Rocket Tie Me to It.mp3 +C:/Users/Rik/Music/Artists/Snow Patrol/A Hundred Million Suns/Snow Patrol - Please Just Take These Photos From My Hands.mp3 +C:/Users/Rik/Music/Artists/Snow Patrol/A Hundred Million Suns/Snow Patrol - Take Back the City.mp3 +C:/Users/Rik/Music/Artists/Snow Patrol/Eyes Open/Snow Patrol - Chasing Cars.mp3 +C:/Users/Rik/Music/Artists/Snow Patrol/Eyes Open/Snow Patrol - Hands Open .mp3 +C:/Users/Rik/Music/Artists/Snow Patrol/Eyes Open/Snow Patrol - Headlights On Dark Roads.mp3 +C:/Users/Rik/Music/Artists/Snow Patrol/Eyes Open/Snow Patrol - In My Arms.mp3 +C:/Users/Rik/Music/Artists/Snow Patrol/Eyes Open/Snow Patrol - It's Beginning to Get to Me.mp3 +C:/Users/Rik/Music/Artists/Snow Patrol/Eyes Open/Snow Patrol - Open Your Eyes .mp3 +C:/Users/Rik/Music/Artists/Snow Patrol/Eyes Open/Snow Patrol - Shut Your Eyes .mp3 +C:/Users/Rik/Music/Artists/Snow Patrol/Eyes Open/Snow Patrol - Warmer Climate.mp3 +C:/Users/Rik/Music/Artists/Snow Patrol/Eyes Open/Snow Patrol - You're All I Have.mp3 +C:/Users/Rik/Music/Artists/Snow Patrol/Snow Patrol - Chocolate.mp3 +C:/Users/Rik/Music/Artists/Snow Patrol/Snow Patrol - Just Say Yes.mp3 +C:/Users/Rik/Music/Artists/Snow Patrol/Snow Patrol - Run.mp3 +C:/Users/Rik/Music/Artists/So They Say/Antidote for Irony/So They Say - Anxiety Is Setting In.mp3 +C:/Users/Rik/Music/Artists/So They Say/Antidote for Irony/So They Say - Good-Bye.mp3 +C:/Users/Rik/Music/Artists/So They Say/Antidote for Irony/So They Say - In Essence We Are Falling.mp3 +C:/Users/Rik/Music/Artists/So They Say/Antidote for Irony/So They Say - In Loving Memory Of....mp3 +C:/Users/Rik/Music/Artists/So They Say/Antidote for Irony/So They Say - Over Exposed Photo.mp3 +C:/Users/Rik/Music/Artists/So They Say/Antidote for Irony/So They Say - Talking In Circles.mp3 +C:/Users/Rik/Music/Artists/So They Say/Antidote for Irony/So They Say - The Burden.mp3 +C:/Users/Rik/Music/Artists/So They Say/Antidote for Irony/So They Say - You Asked, Where Are You Now.mp3 +C:/Users/Rik/Music/Artists/Stone Sour/Audio Secrecy/Stone Sour - Anna.mp3 +C:/Users/Rik/Music/Artists/Stone Sour/Audio Secrecy/Stone Sour - Dying.mp3 +C:/Users/Rik/Music/Artists/Stone Sour/Audio Secrecy/Stone Sour - Hate Not Gone.mp3 +C:/Users/Rik/Music/Artists/Stone Sour/Audio Secrecy/Stone Sour - Hesitate.mp3 +C:/Users/Rik/Music/Artists/Stone Sour/Audio Secrecy/Stone Sour - Home Again.mp3 +C:/Users/Rik/Music/Artists/Stone Sour/Audio Secrecy/Stone Sour - Imperfect.mp3 +C:/Users/Rik/Music/Artists/Stone Sour/Audio Secrecy/Stone Sour - Let's Be Honest.mp3 +C:/Users/Rik/Music/Artists/Stone Sour/Audio Secrecy/Stone Sour - Miracles.mp3 +C:/Users/Rik/Music/Artists/Stone Sour/Audio Secrecy/Stone Sour - Mission Statement.mp3 +C:/Users/Rik/Music/Artists/Stone Sour/Audio Secrecy/Stone Sour - Nylon 66.mp3 +C:/Users/Rik/Music/Artists/Stone Sour/Audio Secrecy/Stone Sour - Pieces.mp3 +C:/Users/Rik/Music/Artists/Stone Sour/Audio Secrecy/Stone Sour - Say You'll Haunt Me.mp3 +C:/Users/Rik/Music/Artists/Stone Sour/Audio Secrecy/Stone Sour - The Bitter End.mp3 +C:/Users/Rik/Music/Artists/Stone Sour/Audio Secrecy/Stone Sour - Threadbare.mp3 +C:/Users/Rik/Music/Artists/Stone Sour/Audio Secrecy/Stone Sour - Unfinished.mp3 +C:/Users/Rik/Music/Artists/Sum 41/Screaming Bloody Murder/Sum 41 - Baby You Don't Wanna Know.mp3 +C:/Users/Rik/Music/Artists/Sum 41/Screaming Bloody Murder/Sum 41 - Back Where I Belong.mp3 +C:/Users/Rik/Music/Artists/Sum 41/Screaming Bloody Murder/Sum 41 - Blood In My Eyes.mp3 +C:/Users/Rik/Music/Artists/Sum 41/Screaming Bloody Murder/Sum 41 - Crash.mp3 +C:/Users/Rik/Music/Artists/Sum 41/Screaming Bloody Murder/Sum 41 - Exit Song.mp3 +C:/Users/Rik/Music/Artists/Sum 41/Screaming Bloody Murder/Sum 41 - Happiness Machine.mp3 +C:/Users/Rik/Music/Artists/Sum 41/Screaming Bloody Murder/Sum 41 - Holy Image of Lies.mp3 +C:/Users/Rik/Music/Artists/Sum 41/Screaming Bloody Murder/Sum 41 - Jessica Kill.mp3 +C:/Users/Rik/Music/Artists/Sum 41/Screaming Bloody Murder/Sum 41 - Reason to Believe (Acoustic).mp3 +C:/Users/Rik/Music/Artists/Sum 41/Screaming Bloody Murder/Sum 41 - Reason to Believe.mp3 +C:/Users/Rik/Music/Artists/Sum 41/Screaming Bloody Murder/Sum 41 - Screaming Bloody Murder.mp3 +C:/Users/Rik/Music/Artists/Sum 41/Screaming Bloody Murder/Sum 41 - Sick of Everyone.mp3 +C:/Users/Rik/Music/Artists/Sum 41/Screaming Bloody Murder/Sum 41 - Skumfuk.mp3 +C:/Users/Rik/Music/Artists/Sum 41/Screaming Bloody Murder/Sum 41 - Time For You to Go.mp3 +C:/Users/Rik/Music/Artists/Sum 41/Screaming Bloody Murder/Sum 41 - What Am I to Say.mp3 +C:/Users/Rik/Music/Artists/Sum 41/Underclass Hero/Sum 41 - Best of Me.mp3 +C:/Users/Rik/Music/Artists/Sum 41/Underclass Hero/Sum 41 - Confusion and Frustration In Modern Times.mp3 +C:/Users/Rik/Music/Artists/Sum 41/Underclass Hero/Sum 41 - Count Your Last Blessings.mp3 +C:/Users/Rik/Music/Artists/Sum 41/Underclass Hero/Sum 41 - Dear Father.mp3 +C:/Users/Rik/Music/Artists/Sum 41/Underclass Hero/Sum 41 - King of Contradiction.mp3 +C:/Users/Rik/Music/Artists/Sum 41/Underclass Hero/Sum 41 - March of the Dogs.mp3 +C:/Users/Rik/Music/Artists/Sum 41/Underclass Hero/Sum 41 - Pull the Curtain.mp3 +C:/Users/Rik/Music/Artists/Sum 41/Underclass Hero/Sum 41 - So Long Goodbye.mp3 +C:/Users/Rik/Music/Artists/Sum 41/Underclass Hero/Sum 41 - Speak of the Devil.mp3 +C:/Users/Rik/Music/Artists/Sum 41/Underclass Hero/Sum 41 - The Jester.mp3 +C:/Users/Rik/Music/Artists/Sum 41/Underclass Hero/Sum 41 - Underclass Hero.mp3 +C:/Users/Rik/Music/Artists/Sum 41/Underclass Hero/Sum 41 - Walking Disaster.mp3 +C:/Users/Rik/Music/Artists/Sum 41/Underclass Hero/Sum 41 - With Me.mp3 +C:/Users/Rik/Music/Artists/The Academy Is/Almost Here/The Academy Is... - Almost Here.mp3 +C:/Users/Rik/Music/Artists/The Academy Is/Almost Here/The Academy Is... - Attention.mp3 +C:/Users/Rik/Music/Artists/The Academy Is/Almost Here/The Academy Is... - Black Mamba.mp3 +C:/Users/Rik/Music/Artists/The Academy Is/Almost Here/The Academy Is... - Checkmarks.mp3 +C:/Users/Rik/Music/Artists/The Academy Is/Almost Here/The Academy Is... - Classifieds.mp3 +C:/Users/Rik/Music/Artists/The Academy Is/Almost Here/The Academy Is... - Down and Out.mp3 +C:/Users/Rik/Music/Artists/The Academy Is/Almost Here/The Academy Is... - Season.mp3 +C:/Users/Rik/Music/Artists/The Academy Is/Almost Here/The Academy Is... - Skeptics and True Believers.mp3 +C:/Users/Rik/Music/Artists/The Academy Is/Almost Here/The Academy Is... - The Phrase That Pays.mp3 +C:/Users/Rik/Music/Artists/The All-American Rejects/Move Along/The All-American Rejects - 11.11 P.M.mp3 +C:/Users/Rik/Music/Artists/The All-American Rejects/Move Along/The All-American Rejects - Change Your Mind.mp3 +C:/Users/Rik/Music/Artists/The All-American Rejects/Move Along/The All-American Rejects - Dance Inside.mp3 +C:/Users/Rik/Music/Artists/The All-American Rejects/Move Along/The All-American Rejects - Dirty Little Secret.mp3 +C:/Users/Rik/Music/Artists/The All-American Rejects/Move Along/The All-American Rejects - I'm Waiting.mp3 +C:/Users/Rik/Music/Artists/The All-American Rejects/Move Along/The All-American Rejects - Move Along.mp3 +C:/Users/Rik/Music/Artists/The All-American Rejects/Move Along/The All-American Rejects - Stab My Back.mp3 +C:/Users/Rik/Music/Artists/The All-American Rejects/Move Along/The All-American Rejects - Top of the World.mp3 +C:/Users/Rik/Music/Artists/The All-American Rejects/When The World Comes Down/The All-American Rejects - Another Heart Calls.mp3 +C:/Users/Rik/Music/Artists/The All-American Rejects/When The World Comes Down/The All-American Rejects - Back to Me.mp3 +C:/Users/Rik/Music/Artists/The All-American Rejects/When The World Comes Down/The All-American Rejects - Believe.mp3 +C:/Users/Rik/Music/Artists/The All-American Rejects/When The World Comes Down/The All-American Rejects - Breakin'.mp3 +C:/Users/Rik/Music/Artists/The All-American Rejects/When The World Comes Down/The All-American Rejects - Damn Girl.mp3 +C:/Users/Rik/Music/Artists/The All-American Rejects/When The World Comes Down/The All-American Rejects - Fallin' Apart.mp3 +C:/Users/Rik/Music/Artists/The All-American Rejects/When The World Comes Down/The All-American Rejects - Gives You Hell.mp3 +C:/Users/Rik/Music/Artists/The All-American Rejects/When The World Comes Down/The All-American Rejects - I Wanna.mp3 +C:/Users/Rik/Music/Artists/The All-American Rejects/When The World Comes Down/The All-American Rejects - Mona Lisa.mp3 +C:/Users/Rik/Music/Artists/The All-American Rejects/When The World Comes Down/The All-American Rejects - Real World.mp3 +C:/Users/Rik/Music/Artists/The All-American Rejects/When The World Comes Down/The All-American Rejects - Sunshine.mp3 +C:/Users/Rik/Music/Artists/The All-American Rejects/When The World Comes Down/The All-American Rejects - The Wind Blows.mp3 +C:/Users/Rik/Music/Artists/The Fray/How To Save A Life/The Fray - All At Once.mp3 +C:/Users/Rik/Music/Artists/The Fray/How To Save A Life/The Fray - Dead Wrong.mp3 +C:/Users/Rik/Music/Artists/The Fray/How To Save A Life/The Fray - Fall Away.mp3 +C:/Users/Rik/Music/Artists/The Fray/How To Save A Life/The Fray - Heaven Forbid.mp3 +C:/Users/Rik/Music/Artists/The Fray/How To Save A Life/The Fray - How to Save a Life.mp3 +C:/Users/Rik/Music/Artists/The Fray/How To Save A Life/The Fray - Hundred.mp3 +C:/Users/Rik/Music/Artists/The Fray/How To Save A Life/The Fray - Little House.mp3 +C:/Users/Rik/Music/Artists/The Fray/How To Save A Life/The Fray - Look After You.mp3 +C:/Users/Rik/Music/Artists/The Fray/How To Save A Life/The Fray - Over My Head (Cable Car).mp3 +C:/Users/Rik/Music/Artists/The Fray/How To Save A Life/The Fray - She Is.mp3 +C:/Users/Rik/Music/Artists/The Fray/How To Save A Life/The Fray - Trust Me.mp3 +C:/Users/Rik/Music/Artists/The Hoosiers/The Illusion Of Safety/The Hoosiers - Bumpy Ride.mp3 +C:/Users/Rik/Music/Artists/The Hoosiers/The Illusion Of Safety/The Hoosiers - Choices.mp3 +C:/Users/Rik/Music/Artists/The Hoosiers/The Illusion Of Safety/The Hoosiers - Giddy Up.mp3 +C:/Users/Rik/Music/Artists/The Hoosiers/The Illusion Of Safety/The Hoosiers - Glorious.mp3 +C:/Users/Rik/Music/Artists/The Hoosiers/The Illusion Of Safety/The Hoosiers - Live By the Ocean.mp3 +C:/Users/Rik/Music/Artists/The Hoosiers/The Illusion Of Safety/The Hoosiers - Made to Measure.mp3 +C:/Users/Rik/Music/Artists/The Hoosiers/The Illusion Of Safety/The Hoosiers - Sarajevo.mp3 +C:/Users/Rik/Music/Artists/The Hoosiers/The Illusion Of Safety/The Hoosiers - Unlikely Hero.mp3 +C:/Users/Rik/Music/Artists/The Hoosiers/The Illusion Of Safety/The Hoosiers - Who Said Anything (About Falling In Love).mp3 +C:/Users/Rik/Music/Artists/The Killers/Day & Age/The Killers - A Crippling Blow.mp3 +C:/Users/Rik/Music/Artists/The Killers/Day & Age/The Killers - A Dustland Fairytale.mp3 +C:/Users/Rik/Music/Artists/The Killers/Day & Age/The Killers - Human.mp3 +C:/Users/Rik/Music/Artists/The Killers/Day & Age/The Killers - I Can't Stay.mp3 +C:/Users/Rik/Music/Artists/The Killers/Day & Age/The Killers - Joy Ride.mp3 +C:/Users/Rik/Music/Artists/The Killers/Day & Age/The Killers - Losing Touch.mp3 +C:/Users/Rik/Music/Artists/The Killers/Day & Age/The Killers - Neon Tiger.mp3 +C:/Users/Rik/Music/Artists/The Killers/Day & Age/The Killers - Spaceman.mp3 +C:/Users/Rik/Music/Artists/The Killers/Day & Age/The Killers - The World We Live In.mp3 +C:/Users/Rik/Music/Artists/The Killers/Day & Age/The Killers - This Is Your Life.mp3 +C:/Users/Rik/Music/Artists/The Killers/Hot Fuss/The Killers - All These Things That I've Done.mp3 +C:/Users/Rik/Music/Artists/The Killers/Hot Fuss/The Killers - Andy, You're a Star.mp3 +C:/Users/Rik/Music/Artists/The Killers/Hot Fuss/The Killers - Believe Me Natalie.mp3 +C:/Users/Rik/Music/Artists/The Killers/Hot Fuss/The Killers - Everything Will Be Alright.mp3 +C:/Users/Rik/Music/Artists/The Killers/Hot Fuss/The Killers - Glamorous Indie Rock & Roll.mp3 +C:/Users/Rik/Music/Artists/The Killers/Hot Fuss/The Killers - Indie Rock & Roll.mp3 +C:/Users/Rik/Music/Artists/The Killers/Hot Fuss/The Killers - Jenny Was a Friend of Mine.mp3 +C:/Users/Rik/Music/Artists/The Killers/Hot Fuss/The Killers - Midnight Show.mp3 +C:/Users/Rik/Music/Artists/The Killers/Hot Fuss/The Killers - Mr Brightside.mp3 +C:/Users/Rik/Music/Artists/The Killers/Hot Fuss/The Killers - Mr. Brightside.mp3 +C:/Users/Rik/Music/Artists/The Killers/Hot Fuss/The Killers - On Top.mp3 +C:/Users/Rik/Music/Artists/The Killers/Hot Fuss/The Killers - Smile Like You Mean It.mp3 +C:/Users/Rik/Music/Artists/The Killers/Hot Fuss/The Killers - The Ballad of Michael Valentine (Bonus).mp3 +C:/Users/Rik/Music/Artists/The Killers/Hot Fuss/The Killers - Under the Gun (Bonus).mp3 +C:/Users/Rik/Music/Artists/The Killers/Hot Fuss/The Killers - Who Let You Go (Bonus).mp3 +C:/Users/Rik/Music/Artists/The Offspring/Greatest Hits/The Offspring - (Can't Get My) Head Around You.mp3 +C:/Users/Rik/Music/Artists/The Offspring/Greatest Hits/The Offspring - All I Want.mp3 +C:/Users/Rik/Music/Artists/The Offspring/Greatest Hits/The Offspring - Can't Repeat.mp3 +C:/Users/Rik/Music/Artists/The Offspring/Greatest Hits/The Offspring - Come Out and Play (Keep 'em Separated).mp3 +C:/Users/Rik/Music/Artists/The Offspring/Greatest Hits/The Offspring - Defy You.mp3 +C:/Users/Rik/Music/Artists/The Offspring/Greatest Hits/The Offspring - Gone Away.mp3 +C:/Users/Rik/Music/Artists/The Offspring/Greatest Hits/The Offspring - Gotta Get Away.mp3 +C:/Users/Rik/Music/Artists/The Offspring/Greatest Hits/The Offspring - Hit That.mp3 +C:/Users/Rik/Music/Artists/The Offspring/Greatest Hits/The Offspring - Original Prankster.mp3 +C:/Users/Rik/Music/Artists/The Offspring/Greatest Hits/The Offspring - Pretty Fly (For a White Guy).mp3 +C:/Users/Rik/Music/Artists/The Offspring/Greatest Hits/The Offspring - Self Esteem.mp3 +C:/Users/Rik/Music/Artists/The Offspring/Greatest Hits/The Offspring - The Kids Aren't Alright.mp3 +C:/Users/Rik/Music/Artists/The Offspring/Greatest Hits/The Offspring - Want You Bad.mp3 +C:/Users/Rik/Music/Artists/The Offspring/Greatest Hits/The Offspring - Why Don't You Get a Job.mp3 +C:/Users/Rik/Music/Artists/The Script/Science & Faith/The Script - Dead Man Walking.mp3 +C:/Users/Rik/Music/Artists/The Script/Science & Faith/The Script - Exit Wounds.mp3 +C:/Users/Rik/Music/Artists/The Script/Science & Faith/The Script - For the First Time.mp3 +C:/Users/Rik/Music/Artists/The Script/Science & Faith/The Script - If You Ever Come Back.mp3 +C:/Users/Rik/Music/Artists/The Script/Science & Faith/The Script - Long Gone and Moved On.mp3 +C:/Users/Rik/Music/Artists/The Script/Science & Faith/The Script - Nothing.mp3 +C:/Users/Rik/Music/Artists/The Script/Science & Faith/The Script - Science & Faith.mp3 +C:/Users/Rik/Music/Artists/The Script/Science & Faith/The Script - This = Love.mp3 +C:/Users/Rik/Music/Artists/The Script/Science & Faith/The Script - You Won't Feel a Thing.mp3 +C:/Users/Rik/Music/Artists/The Script/The Script/The Script - Before the Worst.mp3 +C:/Users/Rik/Music/Artists/The Script/The Script/The Script - Breakeven.mp3 +C:/Users/Rik/Music/Artists/The Script/The Script/The Script - Fall For Anything.mp3 +C:/Users/Rik/Music/Artists/The Script/The Script/The Script - Rusty Halo.mp3 +C:/Users/Rik/Music/Artists/The Script/The Script/The Script - Talk You Down.mp3 +C:/Users/Rik/Music/Artists/The Script/The Script/The Script - The End Is Where I Begin.mp3 +C:/Users/Rik/Music/Artists/The Script/The Script/The Script - The Man Who Can't Be Moved.mp3 +C:/Users/Rik/Music/Artists/Three Days Grace/Life Starts Now/Three Days Grace - Bitter Taste.mp3 +C:/Users/Rik/Music/Artists/Three Days Grace/Life Starts Now/Three Days Grace - Break.mp3 +C:/Users/Rik/Music/Artists/Three Days Grace/Life Starts Now/Three Days Grace - Goin' Down.mp3 +C:/Users/Rik/Music/Artists/Three Days Grace/Life Starts Now/Three Days Grace - Last to Know.mp3 +C:/Users/Rik/Music/Artists/Three Days Grace/Life Starts Now/Three Days Grace - Life Starts Now.mp3 +C:/Users/Rik/Music/Artists/Three Days Grace/Life Starts Now/Three Days Grace - Lost In You.mp3 +C:/Users/Rik/Music/Artists/Three Days Grace/Life Starts Now/Three Days Grace - No More.mp3 +C:/Users/Rik/Music/Artists/Three Days Grace/Life Starts Now/Three Days Grace - Someone Who Cares.mp3 +C:/Users/Rik/Music/Artists/Three Days Grace/Life Starts Now/Three Days Grace - The Good Life.mp3 +C:/Users/Rik/Music/Artists/Three Days Grace/Life Starts Now/Three Days Grace - Without You.mp3 +C:/Users/Rik/Music/Artists/U2/No Line On The Horizon/U2 - Breathe.mp3 +C:/Users/Rik/Music/Artists/U2/No Line On The Horizon/U2 - Get On Your Boots.mp3 +C:/Users/Rik/Music/Artists/U2/No Line On The Horizon/U2 - I'll Go Crazy If I Don't Go Crazy Tonight.mp3 +C:/Users/Rik/Music/Artists/U2/No Line On The Horizon/U2 - Magnificent.mp3 +C:/Users/Rik/Music/Artists/U2/No Line On The Horizon/U2 - No Line On the Horizon.mp3 +C:/Users/Rik/Music/Artists/U2/No Line On The Horizon/U2 - Stand Up Comedy.mp3 +C:/Users/Rik/Music/Artists/U2/No Line On The Horizon/U2 - Unknown Caller.mp3 +C:/Users/Rik/Music/Artists/U2/No Line On The Horizon/U2 - White As Snow.mp3 +C:/Users/Rik/Music/Artists/U2/U2 - Beautiful Day.mp3 +C:/Users/Rik/Music/Artists/U2/U2 - Elevation.mp3 +C:/Users/Rik/Music/Artists/U2/U2 - I Still Haven't Found What I'm Looking For.mp3 +C:/Users/Rik/Music/Artists/U2/U2 - New Year's Day.mp3 +C:/Users/Rik/Music/Artists/U2/U2 - One.mp3 +C:/Users/Rik/Music/Artists/U2/U2 - Stuck In a Moment You Can't Get Out of.mp3 +C:/Users/Rik/Music/Artists/U2/U2 - Sunday Bloody Sunday .mp3 +C:/Users/Rik/Music/Artists/U2/U2 - Sweetest Thing.mp3 +C:/Users/Rik/Music/Artists/U2/U2 - The City of Blinding Lights.mp3 +C:/Users/Rik/Music/Artists/U2/U2 - Vertigo.mp3 +C:/Users/Rik/Music/Artists/U2/U2 - Where the Streets Have No Name.mp3 +C:/Users/Rik/Music/Artists/U2/U2 - With Or Without You.mp3 +C:/Users/Rik/Music/Artists/Weezer/Hurley/Weezer - All My Friends Are Insects (Bonus Track).mp3 +C:/Users/Rik/Music/Artists/Weezer/Hurley/Weezer - Brave New World.mp3 +C:/Users/Rik/Music/Artists/Weezer/Hurley/Weezer - Hang On.mp3 +C:/Users/Rik/Music/Artists/Weezer/Hurley/Weezer - I Want to Be Something (Bonus Track).mp3 +C:/Users/Rik/Music/Artists/Weezer/Hurley/Weezer - Memories.mp3 +C:/Users/Rik/Music/Artists/Weezer/Hurley/Weezer - Represent (Rocked Out Mix) %5Bbonus Track%5D.mp3 +C:/Users/Rik/Music/Artists/Weezer/Hurley/Weezer - Ruling Me.mp3 +C:/Users/Rik/Music/Artists/Weezer/Hurley/Weezer - Run Away.mp3 +C:/Users/Rik/Music/Artists/Weezer/Hurley/Weezer - Smart Girls.mp3 +C:/Users/Rik/Music/Artists/Weezer/Hurley/Weezer - Time Flies.mp3 +C:/Users/Rik/Music/Artists/Weezer/Hurley/Weezer - Trainwrecks.mp3 +C:/Users/Rik/Music/Artists/Weezer/Hurley/Weezer - Unspoken.mp3 +C:/Users/Rik/Music/Artists/Weezer/Hurley/Weezer - Viva La Vida (Bonus Track).mp3 +C:/Users/Rik/Music/Artists/Weezer/Hurley/Weezer - Where's My Sex.mp3 +C:/Users/Rik/Music/Artists/Yellowcard/Paper Walls/Yellowcard - Afraid.mp3 +C:/Users/Rik/Music/Artists/Yellowcard/Paper Walls/Yellowcard - Cut Me, Mick.mp3 +C:/Users/Rik/Music/Artists/Yellowcard/Paper Walls/Yellowcard - Date Line (I Am Gone).mp3 +C:/Users/Rik/Music/Artists/Yellowcard/Paper Walls/Yellowcard - Dear Bobbie.mp3 +C:/Users/Rik/Music/Artists/Yellowcard/Paper Walls/Yellowcard - Fighting.mp3 +C:/Users/Rik/Music/Artists/Yellowcard/Paper Walls/Yellowcard - Five Become Four.mp3 +C:/Users/Rik/Music/Artists/Yellowcard/Paper Walls/Yellowcard - Keeper.mp3 +C:/Users/Rik/Music/Artists/Yellowcard/Paper Walls/Yellowcard - Light Up the Sky.mp3 +C:/Users/Rik/Music/Artists/Yellowcard/Paper Walls/Yellowcard - Paper Walls.mp3 +C:/Users/Rik/Music/Artists/Yellowcard/Paper Walls/Yellowcard - Shadows and Regrets.mp3 +C:/Users/Rik/Music/Artists/Yellowcard/Paper Walls/Yellowcard - Shrink the World.mp3 +C:/Users/Rik/Music/Artists/Yellowcard/Paper Walls/Yellowcard - The Takedown.mp3 +C:/Users/Rik/Music/Artists/Yellowcard/Paper Walls/Yellowcard - You and Me and One Spotlight.mp3 +C:/Users/Rik/Music/Artists/Yellowcard/Yellowcard - October Nights.mp3 +C:/Users/Rik/Music/Artists/You Me At Six/Hold Me Down/You Me At Six - Contagious Chemistry.mp3 +C:/Users/Rik/Music/Artists/You Me At Six/Hold Me Down/You Me At Six - Fireworks.mp3 +C:/Users/Rik/Music/Artists/You Me At Six/Hold Me Down/You Me At Six - Hard to Swallow.mp3 +C:/Users/Rik/Music/Artists/You Me At Six/Hold Me Down/You Me At Six - Liquid Confidence.mp3 +C:/Users/Rik/Music/Artists/You Me At Six/Hold Me Down/You Me At Six - Playing the Blame Game.mp3 +C:/Users/Rik/Music/Artists/You Me At Six/Hold Me Down/You Me At Six - Safer to Hate Her.mp3 +C:/Users/Rik/Music/Artists/You Me At Six/Hold Me Down/You Me At Six - Stay With Me.mp3 +C:/Users/Rik/Music/Artists/You Me At Six/Hold Me Down/You Me At Six - Take Your Breath Away.mp3 +C:/Users/Rik/Music/Artists/You Me At Six/Hold Me Down/You Me At Six - There's No Such Thing As Accident.mp3 +C:/Users/Rik/Music/Artists/You Me At Six/Hold Me Down/You Me At Six - Trophy Eyes.mp3 +C:/Users/Rik/Music/Artists/You Me At Six/Hold Me Down/You Me At Six - Underdog.mp3 +C:/Users/Rik/Music/Old/Bad English - Time Stood Still.mp3 +C:/Users/Rik/Music/Old/Bon Jovi/Bon Jovi - In These Arms.mp3 +C:/Users/Rik/Music/Old/Bon Jovi/Bon Jovi - Livin' On a Prayer.mp3 +C:/Users/Rik/Music/Old/Don Henley - The Boys of Summer.mp3 +C:/Users/Rik/Music/Old/Duran Duran/Duran Duran - Ordinary World.mp3 +C:/Users/Rik/Music/Old/Duran Duran/Duran Duran - The Reflex.mp3 +C:/Users/Rik/Music/Old/Europe - The Final Countdown.mp3 +C:/Users/Rik/Music/Old/Genesis/Genesis - Land of Confusion.mp3 +C:/Users/Rik/Music/Old/Midnight Oil - Beds Are Burning.mp3 +C:/Users/Rik/Music/Old/No Doubt/No Doubt - It's My Life.mp3 +C:/Users/Rik/Music/Old/Survivor - Eye of the Tiger.mp3 +C:/Users/Rik/Music/Various/3 Doors Down/3 Doors Down - Here Without You.mp3 +C:/Users/Rik/Music/Various/3 Doors Down/3 Doors Down - Kryptonite.mp3 +C:/Users/Rik/Music/Various/A Silent Express - Will I Be Around.mp3 +C:/Users/Rik/Music/Various/Adam Lambert - Whataya Want From Me.mp3 +C:/Users/Rik/Music/Various/Alphabeat - The Spell.mp3 +C:/Users/Rik/Music/Various/Anouk/Anouk - Girl.mp3 +C:/Users/Rik/Music/Various/Anouk/Anouk - Nobody's Wife.mp3 +C:/Users/Rik/Music/Various/Anouk/Anouk - R U Kiddin' Me.mp3 +C:/Users/Rik/Music/Various/Avril Lavigne/Avril Lavigne - What the Hell.mp3 +C:/Users/Rik/Music/Various/Biffy Clyro - Many of Horror.mp3 +C:/Users/Rik/Music/Various/Brandon Flowers - Crossfire.mp3 +C:/Users/Rik/Music/Various/Carolina Liar - Show Me What Im Looking For.mp3 +C:/Users/Rik/Music/Various/Chumbawamba - Tubthumping.mp3 +C:/Users/Rik/Music/Various/Eagle Eye Cherry - Save Tonight.mp3 +C:/Users/Rik/Music/Various/Esm%C3%A9e Denters - Outta Here.mp3 +C:/Users/Rik/Music/Various/Falco Luneau - Nobody.mp3 +C:/Users/Rik/Music/Various/Freemasons - Uninvited.mp3 +C:/Users/Rik/Music/Various/Gavin DeGraw/Gavin Degraw - Chariot.mp3 +C:/Users/Rik/Music/Various/Gavin DeGraw/Gavin Degraw - Follow Through.mp3 +C:/Users/Rik/Music/Various/Gavin DeGraw/Gavin Degraw - In Love With a Girl.mp3 +C:/Users/Rik/Music/Various/Intwine - Happy.mp3 +C:/Users/Rik/Music/Various/Jaap - Don't Stop Believin'.mp3 +C:/Users/Rik/Music/Various/Jonas Brothers - Burnin' Up.mp3 +C:/Users/Rik/Music/Various/Joshua Radin - I'd Rather Be With You.mp3 +C:/Users/Rik/Music/Various/Kevin Rudolf - Let It Rock.mp3 +C:/Users/Rik/Music/Various/Kid Rock - All Summer Long.mp3 +C:/Users/Rik/Music/Various/Kylie Minogue/Kylie Minogue - All the Lovers.mp3 +C:/Users/Rik/Music/Various/Kylie Minogue/Kylie Minogue - Get Outta My Way.mp3 +C:/Users/Rik/Music/Various/Kylie Minogue/Kylie Minogue - Love At First Sight.mp3 +C:/Users/Rik/Music/Various/Kylie Minogue/Kylie Minogue - Wow.mp3 +C:/Users/Rik/Music/Various/Lenny Kravitz/Lenny Kravitz - Again.mp3 +C:/Users/Rik/Music/Various/Lenny Kravitz/Lenny Kravitz - Fly Away.mp3 +C:/Users/Rik/Music/Various/Liquido - Narcotic.mp3 +C:/Users/Rik/Music/Various/Live/Live - Heaven.mp3 +C:/Users/Rik/Music/Various/Live/Live - Overcome.mp3 +C:/Users/Rik/Music/Various/Live/Live - Run to the Water.mp3 +C:/Users/Rik/Music/Various/Live/Live - Selling the Drama.mp3 +C:/Users/Rik/Music/Various/Live/Live - The River.mp3 +C:/Users/Rik/Music/Various/Mando Diao - Dance With Somebody.mp3 +C:/Users/Rik/Music/Various/Maroon 5/Maroon 5 - Misery.mp3 +C:/Users/Rik/Music/Various/Maroon 5/Maroon 5 - Won't Go Home Without You.mp3 +C:/Users/Rik/Music/Various/Melee/Melee - Built to Last.mp3 +C:/Users/Rik/Music/Various/Melee/Melee - Imitation.mp3 +C:/Users/Rik/Music/Various/Mike Posner - Cooler Than Me.mp3 +C:/Users/Rik/Music/Various/Novastar/Novastar - Because.mp3 +C:/Users/Rik/Music/Various/Novastar/Novastar - Waiting So Long.mp3 +C:/Users/Rik/Music/Various/Oasis - Wonderwall.mp3 +C:/Users/Rik/Music/Various/One Night Only - Just For Tonight.mp3 +C:/Users/Rik/Music/Various/Robyn - With Every Heartbeat.mp3 +C:/Users/Rik/Music/Various/Roxette/Roxette - How Do You Do!.mp3 +C:/Users/Rik/Music/Various/Roxette/Roxette - It Must Have Been Love.mp3 +C:/Users/Rik/Music/Various/Roxette/Roxette - Joyride.mp3 +C:/Users/Rik/Music/Various/Roxette/Roxette - Listen to Your Heart.mp3 +C:/Users/Rik/Music/Various/Roxette/Roxette - The Look.mp3 +C:/Users/Rik/Music/Various/Scissor Sisters - Fire With Fire.mp3 +C:/Users/Rik/Music/Various/Scouting For Girls - Take a Change On Us.mp3 +C:/Users/Rik/Music/Various/Scouting for Girls/Scouting For Girls - Famous.mp3 +C:/Users/Rik/Music/Various/Scouting for Girls/Scouting For Girls - This Ain't a Love Song.mp3 +C:/Users/Rik/Music/Various/September/September - Can't Get Over.mp3 +C:/Users/Rik/Music/Various/September/September - Cry For You.mp3 +C:/Users/Rik/Music/Various/Sick Puppies - Maybe.mp3 +C:/Users/Rik/Music/Various/Simple Minds - Don't You (Forget About Me).mp3 +C:/Users/Rik/Music/Various/Spin Doctors - Two Princes.mp3 +C:/Users/Rik/Music/Various/Swedish House Mafia - One (Your Name).mp3 +C:/Users/Rik/Music/Various/Taio Cruz - Break Your Heart.mp3 +C:/Users/Rik/Music/Various/The Calling - Wherever You Will Go.mp3 +C:/Users/Rik/Music/Various/The Naked & Famous - Young Blood.mp3 +C:/Users/Rik/Music/Various/The Rasmus - In the Shadows.mp3 +C:/Users/Rik/Music/Various/Train/Train - Drops of Jupiter.mp3 +C:/Users/Rik/Music/Various/Train/Train - Hey, Soul Sister.mp3 +C:/Users/Rik/Music/Various/Train/Train - If It's Love.mp3 +C:/Users/Rik/Music/Various/Wheatus - Teenage Dirtbag.mp3 +C:/Users/Rik/Music/Various/Within Temptation - Faster.mp3 +C:/Users/Rik/Music/Various/Jason Derulo - In My Head.mp3 +C:/Users/Rik/Music/Artists/Foo Fighters/Wasting Light/Foo Fighters - Better Off.mp3 +C:/Users/Rik/Music/Artists/Foo Fighters/Wasting Light/Foo Fighters - I Should Have Known.mp3 +C:/Users/Rik/Music/Artists/Jimmy Eat World/Chase The Light/Jimmy Eat World - Always Be.mp3 +C:/Users/Rik/Music/Artists/Jimmy Eat World/Chase The Light/Jimmy Eat World - Big Casino.mp3 +C:/Users/Rik/Music/Artists/Jimmy Eat World/Chase The Light/Jimmy Eat World - Carry You.mp3 +C:/Users/Rik/Music/Artists/Jimmy Eat World/Chase The Light/Jimmy Eat World - Chase This Light.mp3 +C:/Users/Rik/Music/Artists/Jimmy Eat World/Chase The Light/Jimmy Eat World - Dizzy.mp3 +C:/Users/Rik/Music/Artists/Jimmy Eat World/Chase The Light/Jimmy Eat World - Electable (Give It Up).mp3 +C:/Users/Rik/Music/Artists/Jimmy Eat World/Chase The Light/Jimmy Eat World - Feeling Lucky.mp3 +C:/Users/Rik/Music/Artists/Jimmy Eat World/Chase The Light/Jimmy Eat World - Firefight.mp3 +C:/Users/Rik/Music/Artists/Jimmy Eat World/Chase The Light/Jimmy Eat World - Gotta Be Somebody's Blues.mp3 +C:/Users/Rik/Music/Artists/Jimmy Eat World/Chase The Light/Jimmy Eat World - Here It Goes.mp3 +C:/Users/Rik/Music/Artists/Jimmy Eat World/Chase The Light/Jimmy Eat World - Let It Happen.mp3 +C:/Users/Rik/Music/Artists/Simple Plan/Still Not Getting Any/Simple Plan - Crazy.mp3 +C:/Users/Rik/Music/Artists/Simple Plan/Still Not Getting Any/Simple Plan - Everytime.mp3 +C:/Users/Rik/Music/Artists/Simple Plan/Still Not Getting Any/Simple Plan - Jump.mp3 +C:/Users/Rik/Music/Artists/Simple Plan/Still Not Getting Any/Simple Plan - Me Against The World.mp3 +C:/Users/Rik/Music/Artists/Simple Plan/Still Not Getting Any/Simple Plan - One.mp3 +C:/Users/Rik/Music/Artists/Simple Plan/Still Not Getting Any/Simple Plan - Perfect World.mp3 +C:/Users/Rik/Music/Artists/Simple Plan/Still Not Getting Any/Simple Plan - Promise.mp3 +C:/Users/Rik/Music/Artists/Simple Plan/Still Not Getting Any/Simple Plan - Shut Up.mp3 +C:/Users/Rik/Music/Artists/Simple Plan/Still Not Getting Any/Simple Plan - Thank You.mp3 +C:/Users/Rik/Music/Artists/Simple Plan/Still Not Getting Any/Simple Plan - Untitled.mp3 +C:/Users/Rik/Music/Artists/Simple Plan/Still Not Getting Any/Simple Plan - Welcome To My Life.mp3 +C:/Users/Rik/Music/Artists/Volbeat/Beyond Hell-Above Heaven/Volbeat - 16 Dollars.mp3 +C:/Users/Rik/Music/Artists/Volbeat/Beyond Hell-Above Heaven/Volbeat - 7 Shots.mp3 +C:/Users/Rik/Music/Artists/Volbeat/Beyond Hell-Above Heaven/Volbeat - A Better Believer.mp3 +C:/Users/Rik/Music/Artists/Volbeat/Beyond Hell-Above Heaven/Volbeat - A New Day.mp3 +C:/Users/Rik/Music/Artists/Volbeat/Beyond Hell-Above Heaven/Volbeat - A Warrior's Call.mp3 +C:/Users/Rik/Music/Artists/Volbeat/Beyond Hell-Above Heaven/Volbeat - Being 1.mp3 +C:/Users/Rik/Music/Artists/Volbeat/Beyond Hell-Above Heaven/Volbeat - Fallen.mp3 +C:/Users/Rik/Music/Artists/Volbeat/Beyond Hell-Above Heaven/Volbeat - Heaven Nor Hell.mp3 +C:/Users/Rik/Music/Artists/Volbeat/Beyond Hell-Above Heaven/Volbeat - Magic Zone.mp3 +C:/Users/Rik/Music/Artists/Volbeat/Beyond Hell-Above Heaven/Volbeat - Thanks.mp3 +C:/Users/Rik/Music/Artists/Volbeat/Beyond Hell-Above Heaven/Volbeat - The Mirror and the Ripper.mp3 +C:/Users/Rik/Music/Artists/Volbeat/Beyond Hell-Above Heaven/Volbeat - Who They Are.mp3 +C:/Users/Rik/Music/Various/Beady Eye - The Roller.mp3 +C:/Users/Rik/Music/Various/Depeche Mode - Just Can't Get Enough.mp3 +C:/Users/Rik/Music/Various/Kelly Clarkson/Kelly Clarkson - Because of You.mp3 +C:/Users/Rik/Music/Various/Kelly Clarkson/Kelly Clarkson - Behind These Hazel Eyes.mp3 +C:/Users/Rik/Music/Various/Kelly Clarkson/Kelly Clarkson - Since U Been Gone.mp3 +C:/Users/Rik/Music/Artists/The Gaslight Anthem/American Slang/The Gaslight Anthem - American Slang.mp3 +C:/Users/Rik/Music/Artists/The Gaslight Anthem/American Slang/The Gaslight Anthem - Boxer.mp3 +C:/Users/Rik/Music/Artists/The Gaslight Anthem/American Slang/The Gaslight Anthem - Bring It On.mp3 +C:/Users/Rik/Music/Artists/The Gaslight Anthem/American Slang/The Gaslight Anthem - Old Haunts.mp3 +C:/Users/Rik/Music/Artists/The Gaslight Anthem/American Slang/The Gaslight Anthem - Orphans.mp3 +C:/Users/Rik/Music/Artists/The Gaslight Anthem/American Slang/The Gaslight Anthem - Stay Lucky.mp3 +C:/Users/Rik/Music/Artists/The Gaslight Anthem/American Slang/The Gaslight Anthem - The Diamond Church Street Choir.mp3 +C:/Users/Rik/Music/Artists/The Gaslight Anthem/American Slang/The Gaslight Anthem - The Queen Of Lower Chelsea.mp3 +C:/Users/Rik/Music/Artists/The Gaslight Anthem/American Slang/The Gaslight Anthem - The Spirit Of Jazz.mp3 +C:/Users/Rik/Music/Artists/The Gaslight Anthem/American Slang/The Gaslight Anthem - We Did It When We Were Young.mp3 +C:/Users/Rik/Music/Artists/Blind/Blind/Blind - Break Away.mp3 +C:/Users/Rik/Music/Artists/Blind/Blind/Blind - Every You Every Me.mp3 +C:/Users/Rik/Music/Artists/Blind/Blind/Blind - Jesus Only Knows.mp3 +C:/Users/Rik/Music/Artists/Blind/Blind/Blind - Love Is Gone.mp3 +C:/Users/Rik/Music/Artists/Blind/Blind/Blind - Ordinary Day.mp3 +C:/Users/Rik/Music/Artists/Blind/Blind/Blind - People.mp3 +C:/Users/Rik/Music/Artists/Blind/Blind/Blind - Save Me Now.mp3 +C:/Users/Rik/Music/Artists/Blind/Blind/Blind - These Are the Days.mp3 +C:/Users/Rik/Music/Artists/Blind/Blind/Blind - Today I Break Loose.mp3 +C:/Users/Rik/Music/Artists/Blind/Blind/Blind - Triple X.mp3 +C:/Users/Rik/Music/Artists/Blind/Blind/Blind - Wake Me Up.mp3 +C:/Users/Rik/Music/Artists/Blind/Blind/Blind - We Can Stay.mp3 +C:/Users/Rik/Music/Artists/Blind/Blind/Blind - You.mp3 +C:/Users/Rik/Music/Artists/Cute Is What We Aim For/Rotation/Cute Is What We Aim For - Do What You Do.mp3 +C:/Users/Rik/Music/Artists/Cute Is What We Aim For/Rotation/Cute Is What We Aim For - Doctor.mp3 +C:/Users/Rik/Music/Artists/Cute Is What We Aim For/Rotation/Cute Is What We Aim For - Hollywood.mp3 +C:/Users/Rik/Music/Artists/Cute Is What We Aim For/Rotation/Cute Is What We Aim For - Loser.mp3 +C:/Users/Rik/Music/Artists/Cute Is What We Aim For/Rotation/Cute Is What We Aim For - Marriage to Millions.mp3 +C:/Users/Rik/Music/Artists/Cute Is What We Aim For/Rotation/Cute Is What We Aim For - Miss Sobriety.mp3 +C:/Users/Rik/Music/Artists/Cute Is What We Aim For/Rotation/Cute Is What We Aim For - Navigate Me.mp3 +C:/Users/Rik/Music/Artists/Cute Is What We Aim For/Rotation/Cute Is What We Aim For - Practice Makes Perfect.mp3 +C:/Users/Rik/Music/Artists/Cute Is What We Aim For/Rotation/Cute Is What We Aim For - Safe Ride.mp3 +C:/Users/Rik/Music/Artists/Cute Is What We Aim For/Rotation/Cute Is What We Aim For - The Lock Down Denial.mp3 +C:/Users/Rik/Music/Artists/Cute Is What We Aim For/Rotation/Cute Is What We Aim For - Time.mp3 +C:/Users/Rik/Music/Artists/Kids In Glass Houses/Dirt/Kids In Glass Houses - Artbreaker I.mp3 +C:/Users/Rik/Music/Artists/Kids In Glass Houses/Dirt/Kids In Glass Houses - Artbreaker II.mp3 +C:/Users/Rik/Music/Artists/Kids In Glass Houses/Dirt/Kids In Glass Houses - For Better Or Hearse.mp3 +C:/Users/Rik/Music/Artists/Kids In Glass Houses/Dirt/Kids In Glass Houses - Giving Up.mp3 +C:/Users/Rik/Music/Artists/Kids In Glass Houses/Dirt/Kids In Glass Houses - Hunt the Haunted.mp3 +C:/Users/Rik/Music/Artists/Kids In Glass Houses/Dirt/Kids In Glass Houses - Lilli Rose.mp3 +C:/Users/Rik/Music/Artists/Kids In Glass Houses/Dirt/Kids In Glass Houses - Matters At All.mp3 +C:/Users/Rik/Music/Artists/Kids In Glass Houses/Dirt/Kids In Glass Houses - Maybe Tomorrow.mp3 +C:/Users/Rik/Music/Artists/Kids In Glass Houses/Dirt/Kids In Glass Houses - Sunshine.mp3 +C:/Users/Rik/Music/Artists/Kids In Glass Houses/Dirt/Kids In Glass Houses - The Best Is Yet To Come.mp3 +C:/Users/Rik/Music/Artists/Kids In Glass Houses/Dirt/Kids In Glass Houses - The Morning Afterlife.mp3 +C:/Users/Rik/Music/Artists/Kids In Glass Houses/Dirt/Kids In Glass Houses - Undercover Lover.mp3 +C:/Users/Rik/Music/Artists/Kids In Glass Houses/Dirt/Kids In Glass Houses - Youngblood (Let It Out).mp3 +C:/Users/Rik/Music/Artists/Simple Plan/Get Your Heart On!/Simple Plan - Anywhere Else But Here.mp3 +C:/Users/Rik/Music/Artists/Simple Plan/Get Your Heart On!/Simple Plan - Astronaut.mp3 +C:/Users/Rik/Music/Artists/Simple Plan/Get Your Heart On!/Simple Plan - Can't Keep My Hands Off You.mp3 +C:/Users/Rik/Music/Artists/Simple Plan/Get Your Heart On!/Simple Plan - Freaking Me Out.mp3 +C:/Users/Rik/Music/Artists/Simple Plan/Get Your Heart On!/Simple Plan - Gone Too Soon.mp3 +C:/Users/Rik/Music/Artists/Simple Plan/Get Your Heart On!/Simple Plan - Jet Lag.mp3 +C:/Users/Rik/Music/Artists/Simple Plan/Get Your Heart On!/Simple Plan - Last One Standing.mp3 +C:/Users/Rik/Music/Artists/Simple Plan/Get Your Heart On!/Simple Plan - Loser Of The Year.mp3 +C:/Users/Rik/Music/Artists/Simple Plan/Get Your Heart On!/Simple Plan - This Song Saved My Life.mp3 +C:/Users/Rik/Music/Artists/Simple Plan/Get Your Heart On!/Simple Plan - You Suck At Love.mp3 +C:/Users/Rik/Music/Various/The Von Bondies - C%60Mon C%60Mon.mp3 +C:/Users/Rik/Music/Various/White Stripes - Seven Nation Army.mp3 +C:/Users/Rik/Music/Artists/Futures/The Holiday/Futures - 16.mp3 +C:/Users/Rik/Music/Artists/Futures/The Holiday/Futures - Holiday.mp3 +C:/Users/Rik/Music/Artists/Futures/The Holiday/Futures - Sal Paradise.mp3 +C:/Users/Rik/Music/Artists/Futures/The Holiday/Futures - Take Me Home.mp3 +C:/Users/Rik/Music/Artists/Futures/The Holiday/Futures - Thank You.mp3 +C:/Users/Rik/Music/Artists/Futures/The Holiday/Futures - The Boy Who Cried Wolf.mp3 +C:/Users/Rik/Music/Artists/Futures/The Holiday/Futures - The Summer.mp3 +C:/Users/Rik/Music/Artists/Rise Against/Appeal To Reason/Rise Against - Audience of One.mp3 +C:/Users/Rik/Music/Artists/Rise Against/Appeal To Reason/Rise Against - Collapse (Post-Amerika).mp3 +C:/Users/Rik/Music/Artists/Rise Against/Appeal To Reason/Rise Against - Elective Amnesia.mp3 +C:/Users/Rik/Music/Artists/Rise Against/Appeal To Reason/Rise Against - Entertainment.mp3 +C:/Users/Rik/Music/Artists/Rise Against/Appeal To Reason/Rise Against - From Heads Unworthy.mp3 +C:/Users/Rik/Music/Artists/Rise Against/Appeal To Reason/Rise Against - Hairline Fracture.mp3 +C:/Users/Rik/Music/Artists/Rise Against/Appeal To Reason/Rise Against - Hero of War.mp3 +C:/Users/Rik/Music/Artists/Rise Against/Appeal To Reason/Rise Against - Kotov Syndrome.mp3 +C:/Users/Rik/Music/Artists/Rise Against/Appeal To Reason/Rise Against - Long Forgotten Sons.mp3 +C:/Users/Rik/Music/Artists/Rise Against/Appeal To Reason/Rise Against - Prayer of the Refugee.mp3 +C:/Users/Rik/Music/Artists/Rise Against/Appeal To Reason/Rise Against - Re-Education (Through Labor).mp3 +C:/Users/Rik/Music/Artists/Rise Against/Appeal To Reason/Rise Against - Savior.mp3 +C:/Users/Rik/Music/Artists/Rise Against/Appeal To Reason/Rise Against - The Dirt Whispered.mp3 +C:/Users/Rik/Music/Artists/Rise Against/Appeal To Reason/Rise Against - The Strength to Go On.mp3 +C:/Users/Rik/Music/Artists/Rise Against/Appeal To Reason/Rise Against - Whereabouts Unknown.mp3 +C:/Users/Rik/Music/Artists/White Lies/To Lose My Life/White Lies - A Place To Hide.mp3 +C:/Users/Rik/Music/Artists/White Lies/To Lose My Life/White Lies - Death.mp3 +C:/Users/Rik/Music/Artists/White Lies/To Lose My Life/White Lies - E.S.T..mp3 +C:/Users/Rik/Music/Artists/White Lies/To Lose My Life/White Lies - Farewell To The Fairground.mp3 +C:/Users/Rik/Music/Artists/White Lies/To Lose My Life/White Lies - Fifty On Our Foreheads.mp3 +C:/Users/Rik/Music/Artists/White Lies/To Lose My Life/White Lies - From The Stars.mp3 +C:/Users/Rik/Music/Artists/White Lies/To Lose My Life/White Lies - Nothing To Give.mp3 +C:/Users/Rik/Music/Artists/White Lies/To Lose My Life/White Lies - The Price Of Love.mp3 +C:/Users/Rik/Music/Artists/White Lies/To Lose My Life/White Lies - To Lose My Life.mp3 +C:/Users/Rik/Music/Artists/White Lies/To Lose My Life/White Lies - Unfinished Business.mp3 +C:/Users/Rik/Music/Artists/Yellowcard/When You're Through Thinking, Say Yes/Yellowcard - Be the Young.mp3 +C:/Users/Rik/Music/Artists/Yellowcard/When You're Through Thinking, Say Yes/Yellowcard - For You and Your Denial.mp3 +C:/Users/Rik/Music/Artists/Yellowcard/When You're Through Thinking, Say Yes/Yellowcard - Hang You Up.mp3 +C:/Users/Rik/Music/Artists/Yellowcard/When You're Through Thinking, Say Yes/Yellowcard - Hide.mp3 +C:/Users/Rik/Music/Artists/Yellowcard/When You're Through Thinking, Say Yes/Yellowcard - Life of Leaving Home.mp3 +C:/Users/Rik/Music/Artists/Yellowcard/When You're Through Thinking, Say Yes/Yellowcard - Promises.mp3 +C:/Users/Rik/Music/Artists/Yellowcard/When You're Through Thinking, Say Yes/Yellowcard - See Me Smiling.mp3 +C:/Users/Rik/Music/Artists/Yellowcard/When You're Through Thinking, Say Yes/Yellowcard - Sing for Me (Acoustic).mp3 +C:/Users/Rik/Music/Artists/Yellowcard/When You're Through Thinking, Say Yes/Yellowcard - Sing for Me.mp3 +C:/Users/Rik/Music/Artists/Yellowcard/When You're Through Thinking, Say Yes/Yellowcard - Soundtrack.mp3 +C:/Users/Rik/Music/Artists/Yellowcard/When You're Through Thinking, Say Yes/Yellowcard - The Sound of You and Me.mp3 +C:/Users/Rik/Music/Artists/Yellowcard/When You're Through Thinking, Say Yes/Yellowcard - With You Around.mp3 +C:/Users/Rik/Music/Artists/Fall Out Boy/Infinity On High/Fall Out Boy - Bang The Doldrums.mp3 +C:/Users/Rik/Music/Artists/Fall Out Boy/Infinity On High/Fall Out Boy - Don't You Know Who I Think I Am.mp3 +C:/Users/Rik/Music/Artists/Fall Out Boy/Infinity On High/Fall Out Boy - Fame.mp3 +C:/Users/Rik/Music/Artists/Fall Out Boy/Infinity On High/Fall Out Boy - Hum Hallelujah.mp3 +C:/Users/Rik/Music/Artists/Fall Out Boy/Infinity On High/Fall Out Boy - I'm Like A Lawyer With The Way I'm Always Trying To Get You Off (me+you).mp3 +C:/Users/Rik/Music/Artists/Fall Out Boy/Infinity On High/Fall Out Boy - I've Got All This Ringing In My Ears And None On My Fingers.mp3 +C:/Users/Rik/Music/Artists/Fall Out Boy/Infinity On High/Fall Out Boy - Thanks For The Memories.mp3 +C:/Users/Rik/Music/Artists/Fall Out Boy/Infinity On High/Fall Out Boy - The (After) Life Of The Party.mp3 +C:/Users/Rik/Music/Artists/Fall Out Boy/Infinity On High/Fall Out Boy - The Carpal Tunnel Of Love.mp3 +C:/Users/Rik/Music/Artists/Fall Out Boy/Infinity On High/Fall Out Boy - The Take Over, The Breaks Over.mp3 +C:/Users/Rik/Music/Artists/Fall Out Boy/Infinity On High/Fall Out Boy - This Ain't A Scene, It's An Arms Race.mp3 +C:/Users/Rik/Music/Artists/Fall Out Boy/Infinity On High/Fall Out Boy - Thriller.mp3 +C:/Users/Rik/Music/Artists/Fall Out Boy/Infinity On High/Fall Out Boy - You're Crashing, But You're No Wave.mp3 +C:/Users/Rik/Music/Artists/Jimmy Eat World/Invented/Jimmy Eat World - Action Needs An Audience.mp3 +C:/Users/Rik/Music/Artists/Jimmy Eat World/Invented/Jimmy Eat World - Coffee And Cigarettes.mp3 +C:/Users/Rik/Music/Artists/Jimmy Eat World/Invented/Jimmy Eat World - Cut.mp3 +C:/Users/Rik/Music/Artists/Jimmy Eat World/Invented/Jimmy Eat World - Evidence.mp3 +C:/Users/Rik/Music/Artists/Jimmy Eat World/Invented/Jimmy Eat World - Heart Is Hard To Find.mp3 +C:/Users/Rik/Music/Artists/Jimmy Eat World/Invented/Jimmy Eat World - Higher Devotion.mp3 +C:/Users/Rik/Music/Artists/Jimmy Eat World/Invented/Jimmy Eat World - Invented.mp3 +C:/Users/Rik/Music/Artists/Jimmy Eat World/Invented/Jimmy Eat World - Littlething.mp3 +C:/Users/Rik/Music/Artists/Jimmy Eat World/Invented/Jimmy Eat World - Mixtape.mp3 +C:/Users/Rik/Music/Artists/Jimmy Eat World/Invented/Jimmy Eat World - Movielike.mp3 +C:/Users/Rik/Music/Artists/Jimmy Eat World/Invented/Jimmy Eat World - My Best Theory.mp3 +C:/Users/Rik/Music/Artists/Jimmy Eat World/Invented/Jimmy Eat World - Stop.mp3 +C:/Users/Rik/Music/Artists/Red/Until We Have Faces/Red - Best Is Yet to Come.mp3 +C:/Users/Rik/Music/Artists/Red/Until We Have Faces/Red - Buried Beneath.mp3 +C:/Users/Rik/Music/Artists/Red/Until We Have Faces/Red - Faceless.mp3 +C:/Users/Rik/Music/Artists/Red/Until We Have Faces/Red - Feed the Machine.mp3 +C:/Users/Rik/Music/Artists/Red/Until We Have Faces/Red - Hymn for the Missing.mp3 +C:/Users/Rik/Music/Artists/Red/Until We Have Faces/Red - Let It Burn.mp3 +C:/Users/Rik/Music/Artists/Red/Until We Have Faces/Red - Lie to Me (Denial).mp3 +C:/Users/Rik/Music/Artists/Red/Until We Have Faces/Red - Not Alone.mp3 +C:/Users/Rik/Music/Artists/Red/Until We Have Faces/Red - The Outside.mp3 +C:/Users/Rik/Music/Artists/Red/Until We Have Faces/Red - Watch You Crawl.mp3 +C:/Users/Rik/Music/Artists/Red/Until We Have Faces/Red - Who We Are.mp3 +C:/Users/Rik/Music/Artists/Framing Hanley/A Promise To Burn/Framing Hanley - Back To Go Again.mp3 +C:/Users/Rik/Music/Artists/Framing Hanley/A Promise To Burn/Framing Hanley - Bittersweet Sundown.mp3 +C:/Users/Rik/Music/Artists/Framing Hanley/A Promise To Burn/Framing Hanley - Fool With Dreams.mp3 +C:/Users/Rik/Music/Artists/Framing Hanley/A Promise To Burn/Framing Hanley - Intro.mp3 +C:/Users/Rik/Music/Artists/Framing Hanley/A Promise To Burn/Framing Hanley - Livin' So Divine.mp3 +C:/Users/Rik/Music/Artists/Framing Hanley/A Promise To Burn/Framing Hanley - Photographs & Gasoline.mp3 +C:/Users/Rik/Music/Artists/Framing Hanley/A Promise To Burn/Framing Hanley - The Burn.mp3 +C:/Users/Rik/Music/Artists/Framing Hanley/A Promise To Burn/Framing Hanley - The Promise.mp3 +C:/Users/Rik/Music/Artists/Framing Hanley/A Promise To Burn/Framing Hanley - Wake Up.mp3 +C:/Users/Rik/Music/Artists/Framing Hanley/A Promise To Burn/Framing Hanley - WarZone.mp3 +C:/Users/Rik/Music/Artists/Framing Hanley/A Promise To Burn/Framing Hanley - Weight of The World.mp3 +C:/Users/Rik/Music/Artists/Framing Hanley/A Promise To Burn/Framing Hanley - You Stupid Girl.mp3 +C:/Users/Rik/Music/Artists/Framing Hanley/A Promise To Burn/Framing Hanley - You.mp3 +C:/Users/Rik/Music/Artists/Anberlin/Cities/Anberlin - (Fin).mp3 +C:/Users/Rik/Music/Artists/Anberlin/Cities/Anberlin - A Whisper & A Clamour.mp3 +C:/Users/Rik/Music/Artists/Anberlin/Cities/Anberlin - Adelaide.mp3 +C:/Users/Rik/Music/Artists/Anberlin/Cities/Anberlin - Alexithymia.mp3 +C:/Users/Rik/Music/Artists/Anberlin/Cities/Anberlin - Debut.mp3 +C:/Users/Rik/Music/Artists/Anberlin/Cities/Anberlin - Dismantle. Repair.mp3 +C:/Users/Rik/Music/Artists/Anberlin/Cities/Anberlin - Godspeed.mp3 +C:/Users/Rik/Music/Artists/Anberlin/Cities/Anberlin - Hello Alone.mp3 +C:/Users/Rik/Music/Artists/Anberlin/Cities/Anberlin - Inevitable.mp3 +C:/Users/Rik/Music/Artists/Anberlin/Cities/Anberlin - Reclusion.mp3 +C:/Users/Rik/Music/Artists/Anberlin/Cities/Anberlin - The Promise.mp3 +C:/Users/Rik/Music/Artists/Anberlin/Cities/Anberlin - The Unwinding Cable Car.mp3 +C:/Users/Rik/Music/Artists/Anberlin/Cities/Anberlin - There Is A Light That Never Goes Dope.mp3 +C:/Users/Rik/Music/Artists/Anberlin/Cities/Anberlin - There Is No Mathematics To Love And Loss.mp3 +C:/Users/Rik/Music/Artists/Anberlin/Cities/Anberlin - Uncanny.mp3 +C:/Users/Rik/Music/Artists/Anberlin/New Surrender/Anberlin - Blame Me! Blame Me!.mp3 +C:/Users/Rik/Music/Artists/Anberlin/New Surrender/Anberlin - Breaking.mp3 +C:/Users/Rik/Music/Artists/Anberlin/New Surrender/Anberlin - Breathe.mp3 +C:/Users/Rik/Music/Artists/Anberlin/New Surrender/Anberlin - Burn Out Brighter (Northern Lights).mp3 +C:/Users/Rik/Music/Artists/Anberlin/New Surrender/Anberlin - Disappear.mp3 +C:/Users/Rik/Music/Artists/Anberlin/New Surrender/Anberlin - Feel Good Drag.mp3 +C:/Users/Rik/Music/Artists/Anberlin/New Surrender/Anberlin - Haight St.mp3 +C:/Users/Rik/Music/Artists/Anberlin/New Surrender/Anberlin - Misearbile Visu (Ex Malo Bonum).mp3 +C:/Users/Rik/Music/Artists/Anberlin/New Surrender/Anberlin - Retrace.mp3 +C:/Users/Rik/Music/Artists/Anberlin/New Surrender/Anberlin - Soft Skeletons.mp3 +C:/Users/Rik/Music/Artists/Anberlin/New Surrender/Anberlin - The Resistance.mp3 +C:/Users/Rik/Music/Artists/Anberlin/New Surrender/Anberlin - Younglife.mp3 +C:/Users/Rik/Music/Artists/Arcade Fire/Neon Bible/Arcade Fire - Antichrist Television Blues.mp3 +C:/Users/Rik/Music/Artists/Arcade Fire/Neon Bible/Arcade Fire - Black Mirror.mp3 +C:/Users/Rik/Music/Artists/Arcade Fire/Neon Bible/Arcade Fire - Black WaveBad Vibrations.mp3 +C:/Users/Rik/Music/Artists/Arcade Fire/Neon Bible/Arcade Fire - Intervention.mp3 +C:/Users/Rik/Music/Artists/Arcade Fire/Neon Bible/Arcade Fire - Keep The Car Running.mp3 +C:/Users/Rik/Music/Artists/Arcade Fire/Neon Bible/Arcade Fire - No Cars Go.mp3 +C:/Users/Rik/Music/Artists/Arcade Fire/Neon Bible/Arcade Fire - Ocean Of Noise.mp3 +C:/Users/Rik/Music/Artists/Arcade Fire/Neon Bible/Arcade Fire - Well & The Lighthouse, The.mp3 +C:/Users/Rik/Music/Artists/Arcade Fire/Neon Bible/Arcade Fire - Windowsill.mp3 +C:/Users/Rik/Music/Artists/Green Day/21st Century Breakdown/Green Day - %C2%A1Viva la Gloria!.mp3 +C:/Users/Rik/Music/Artists/The Gaslight Anthem/Sink or Swim/The Gaslight Anthem - 1990.mp3 +C:/Users/Rik/Music/Artists/The Gaslight Anthem/Sink or Swim/The Gaslight Anthem - Angry Johnny and the Radio.mp3 +C:/Users/Rik/Music/Artists/The Gaslight Anthem/Sink or Swim/The Gaslight Anthem - Bomboxes and Dictionaries.mp3 +C:/Users/Rik/Music/Artists/The Gaslight Anthem/Sink or Swim/The Gaslight Anthem - Drive.mp3 +C:/Users/Rik/Music/Artists/The Gaslight Anthem/Sink or Swim/The Gaslight Anthem - I Coul'da Been a Contender.mp3 +C:/Users/Rik/Music/Artists/The Gaslight Anthem/Sink or Swim/The Gaslight Anthem - I'da Called You Woody, Joe.mp3 +C:/Users/Rik/Music/Artists/The Gaslight Anthem/Sink or Swim/The Gaslight Anthem - Red in the Morning.mp3 +C:/Users/Rik/Music/Artists/The Gaslight Anthem/Sink or Swim/The Gaslight Anthem - We Came to Dance.mp3 +C:/Users/Rik/Music/Artists/The Gaslight Anthem/Sink or Swim/The Gaslight Anthem - We're Getting A Divorce, You Keep The Dinner.mp3 +C:/Users/Rik/Music/Artists/The Gaslight Anthem/Sink or Swim/The Gaslight Anthem - Wooderson.mp3 +C:/Users/Rik/Music/Artists/Volbeat/Guitar Gangsters & Cadillac Blood/Volbeat - Back To Prom.mp3 +C:/Users/Rik/Music/Artists/Volbeat/Guitar Gangsters & Cadillac Blood/Volbeat - Broken Man And The Dawn.mp3 +C:/Users/Rik/Music/Artists/Volbeat/Guitar Gangsters & Cadillac Blood/Volbeat - End Of The Road.mp3 +C:/Users/Rik/Music/Artists/Volbeat/Guitar Gangsters & Cadillac Blood/Volbeat - Find That Soul.mp3 +C:/Users/Rik/Music/Artists/Volbeat/Guitar Gangsters & Cadillac Blood/Volbeat - Guitar Gangsters & Cadillac Blood.mp3 +C:/Users/Rik/Music/Artists/Volbeat/Guitar Gangsters & Cadillac Blood/Volbeat - Hallelujah Goat.mp3 +C:/Users/Rik/Music/Artists/Volbeat/Guitar Gangsters & Cadillac Blood/Volbeat - I'm So Lonesome I Could Cry.mp3 +C:/Users/Rik/Music/Artists/Volbeat/Guitar Gangsters & Cadillac Blood/Volbeat - Light A Way.mp3 +C:/Users/Rik/Music/Artists/Volbeat/Guitar Gangsters & Cadillac Blood/Volbeat - Making Believe.mp3 +C:/Users/Rik/Music/Artists/Volbeat/Guitar Gangsters & Cadillac Blood/Volbeat - Mary Ann' s Place.mp3 +C:/Users/Rik/Music/Artists/Volbeat/Guitar Gangsters & Cadillac Blood/Volbeat - Maybellene I Hofteholder.mp3 +C:/Users/Rik/Music/Artists/Volbeat/Guitar Gangsters & Cadillac Blood/Volbeat - Still Counting.mp3 +C:/Users/Rik/Music/Artists/Volbeat/Guitar Gangsters & Cadillac Blood/Volbeat - We.mp3 +C:/Users/Rik/Music/Artists/Volbeat/Guitar Gangsters & Cadillac Blood/Volbeat - Wild Rover Of Hell.mp3 +C:/Users/Rik/Music/Artists/My Chemical Romance/Danger Days - The True Lives Of The Fabulous Killjoys/My Chemical Romance - Bulletproof Heart.mp3 +C:/Users/Rik/Music/Artists/My Chemical Romance/Danger Days - The True Lives Of The Fabulous Killjoys/My Chemical Romance - Destroya.mp3 +C:/Users/Rik/Music/Artists/My Chemical Romance/Danger Days - The True Lives Of The Fabulous Killjoys/My Chemical Romance - Party Poison.mp3 +C:/Users/Rik/Music/Artists/My Chemical Romance/Danger Days - The True Lives Of The Fabulous Killjoys/My Chemical Romance - Planetary (Go!).mp3 +C:/Users/Rik/Music/Artists/My Chemical Romance/Danger Days - The True Lives Of The Fabulous Killjoys/My Chemical Romance - Save Yourself- I'll Hold Them Back.mp3 +C:/Users/Rik/Music/Artists/My Chemical Romance/Danger Days - The True Lives Of The Fabulous Killjoys/My Chemical Romance - S-C-A-R-E-C-R-O-W.mp3 +C:/Users/Rik/Music/Artists/My Chemical Romance/Danger Days - The True Lives Of The Fabulous Killjoys/My Chemical Romance - Sing.mp3 +C:/Users/Rik/Music/Artists/My Chemical Romance/Danger Days - The True Lives Of The Fabulous Killjoys/My Chemical Romance - Summertime.mp3 +C:/Users/Rik/Music/Artists/My Chemical Romance/Danger Days - The True Lives Of The Fabulous Killjoys/My Chemical Romance - The Kids From Yesterday.mp3 +C:/Users/Rik/Music/Artists/My Chemical Romance/Danger Days - The True Lives Of The Fabulous Killjoys/My Chemical Romance - The Only Hope For Me Is You.mp3 +C:/Users/Rik/Music/Artists/My Chemical Romance/Danger Days - The True Lives Of The Fabulous Killjoys/My Chemical Romance - Vampire Money.mp3 +C:/Users/Rik/Music/Artists/Longwave/Secrets Are Sinister/Longwave - Eyes Like Headlights.mp3 +C:/Users/Rik/Music/Artists/Longwave/Secrets Are Sinister/Longwave - I Don't Dare.mp3 +C:/Users/Rik/Music/Artists/Longwave/Secrets Are Sinister/Longwave - It's True.mp3 +C:/Users/Rik/Music/Artists/Longwave/Secrets Are Sinister/Longwave - Life Is Wrong.mp3 +C:/Users/Rik/Music/Artists/Longwave/Secrets Are Sinister/Longwave - No Direction.mp3 +C:/Users/Rik/Music/Artists/Longwave/Secrets Are Sinister/Longwave - Satellites.mp3 +C:/Users/Rik/Music/Artists/Longwave/Secrets Are Sinister/Longwave - Secrets Are Sinister.mp3 +C:/Users/Rik/Music/Artists/Longwave/Secrets Are Sinister/Longwave - Shining Hours.mp3 +C:/Users/Rik/Music/Artists/Longwave/Secrets Are Sinister/Longwave - Sideways Sideways Rain.mp3 +C:/Users/Rik/Music/Artists/Longwave/Secrets Are Sinister/Longwave - Sirens In The Deep Sea.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/I'm With You/Red Hot Chili Peppers - Annie Wants a Baby.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/I'm With You/Red Hot Chili Peppers - Brendan's Death Song.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/I'm With You/Red Hot Chili Peppers - Dance, Dance, Dance.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/I'm With You/Red Hot Chili Peppers - Did I Let You Know.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/I'm With You/Red Hot Chili Peppers - Ethiopia.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/I'm With You/Red Hot Chili Peppers - Even You Brutus.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/I'm With You/Red Hot Chili Peppers - Factory of Faith.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/I'm With You/Red Hot Chili Peppers - Goodbye Hooray.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/I'm With You/Red Hot Chili Peppers - Happiness Loves Company.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/I'm With You/Red Hot Chili Peppers - Look Around.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/I'm With You/Red Hot Chili Peppers - Meet Me At the Corner.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/I'm With You/Red Hot Chili Peppers - Monarchy of Roses.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/I'm With You/Red Hot Chili Peppers - Police Station.mp3 +C:/Users/Rik/Music/Artists/Red Hot Chili Peppers/I'm With You/Red Hot Chili Peppers - The Adventures of Rain Dance Maggie.mp3 +C:/Users/Rik/Music/Artists/Amber Pacific/Virtues/Amber Pacific - An Anthem For The Young At Heart.mp3 +C:/Users/Rik/Music/Artists/Amber Pacific/Virtues/Amber Pacific - Burdens Of The Past.mp3 +C:/Users/Rik/Music/Artists/Amber Pacific/Virtues/Amber Pacific - Conviction.mp3 +C:/Users/Rik/Music/Artists/Amber Pacific/Virtues/Amber Pacific - Shine.mp3 +C:/Users/Rik/Music/Artists/Amber Pacific/Virtues/Amber Pacific - Something To Be Said.mp3 +C:/Users/Rik/Music/Artists/Amber Pacific/Virtues/Amber Pacific - The Best Mistake.mp3 +C:/Users/Rik/Music/Artists/Amber Pacific/Virtues/Amber Pacific - The Girl Who Destroys.mp3 +C:/Users/Rik/Music/Artists/Amber Pacific/Virtues/Amber Pacific - The Good Life.mp3 +C:/Users/Rik/Music/Artists/Amber Pacific/Virtues/Amber Pacific - Three Words.mp3 +C:/Users/Rik/Music/Artists/Amber Pacific/Virtues/Amber Pacific - We Can't Fake This.mp3 +C:/Users/Rik/Music/Artists/Amber Pacific/Virtues/Amber Pacific - What Matters Most.mp3 +C:/Users/Rik/Music/Old/Nirvana - Smells Like Teen Spirit.mp3 +C:/Users/Rik/Music/Artists/10 Years Feeding/Feeding the Wolves/10 Years - Don't Fight It.mp3 +C:/Users/Rik/Music/Artists/Cold War Kids/Mine Is Yours/Cold War Kids - Broken Open.mp3 +C:/Users/Rik/Music/Artists/Cold War Kids/Mine Is Yours/Cold War Kids - Bulldozer.mp3 +C:/Users/Rik/Music/Artists/Cold War Kids/Mine Is Yours/Cold War Kids - Cold Toes On The Cold Floor.mp3 +C:/Users/Rik/Music/Artists/Cold War Kids/Mine Is Yours/Cold War Kids - Finally Begin.mp3 +C:/Users/Rik/Music/Artists/Cold War Kids/Mine Is Yours/Cold War Kids - Louder Than Ever.mp3 +C:/Users/Rik/Music/Artists/Cold War Kids/Mine Is Yours/Cold War Kids - Mine Is Yours.mp3 +C:/Users/Rik/Music/Artists/Cold War Kids/Mine Is Yours/Cold War Kids - Out Of The Wilderness.mp3 +C:/Users/Rik/Music/Artists/Cold War Kids/Mine Is Yours/Cold War Kids - Royal Blue.mp3 +C:/Users/Rik/Music/Artists/Cold War Kids/Mine Is Yours/Cold War Kids - Sensitive Kid.mp3 +C:/Users/Rik/Music/Artists/Cold War Kids/Mine Is Yours/Cold War Kids - Skip The Charades.mp3 +C:/Users/Rik/Music/Artists/Sum 41/Screaming Bloody Murder/Sum 41 - We're the Same.mp3 +C:/Users/Rik/Music/Artists/Maximo Park/Our Earthly Pleasures/Maximo Park - A Fortnight's Time.mp3 +C:/Users/Rik/Music/Artists/Maximo Park/Our Earthly Pleasures/Maximo Park - Books From Boxes.mp3 +C:/Users/Rik/Music/Artists/Maximo Park/Our Earthly Pleasures/Maximo Park - By The Monument.mp3 +C:/Users/Rik/Music/Artists/Maximo Park/Our Earthly Pleasures/Maximo Park - Girls Who Play Guitars.mp3 +C:/Users/Rik/Music/Artists/Maximo Park/Our Earthly Pleasures/Maximo Park - Karaoke Plays.mp3 +C:/Users/Rik/Music/Artists/Maximo Park/Our Earthly Pleasures/Maximo Park - Nosebleed.mp3 +C:/Users/Rik/Music/Artists/Maximo Park/Our Earthly Pleasures/Maximo Park - Our Velocity.mp3 +C:/Users/Rik/Music/Artists/Maximo Park/Our Earthly Pleasures/Maximo Park - Parisian Skies.mp3 +C:/Users/Rik/Music/Artists/Maximo Park/Our Earthly Pleasures/Maximo Park - Russian Literature.mp3 +C:/Users/Rik/Music/Artists/Maximo Park/Our Earthly Pleasures/Maximo Park - Sandblasted And Set Free.mp3 +C:/Users/Rik/Music/Artists/Maximo Park/Our Earthly Pleasures/Maximo Park - The Unshockable.mp3 +C:/Users/Rik/Music/Artists/Maximo Park/Our Earthly Pleasures/Maximo Park - Your Urge.mp3 +C:/Users/Rik/Music/Artists/Stereophonics/Keep Calm and Carry On/Stereophonics - 100MPH.mp3 +C:/Users/Rik/Music/Artists/Stereophonics/Keep Calm and Carry On/Stereophonics - Beerbottle.mp3 +C:/Users/Rik/Music/Artists/Stereophonics/Keep Calm and Carry On/Stereophonics - Could You Be The One.mp3 +C:/Users/Rik/Music/Artists/Stereophonics/Keep Calm and Carry On/Stereophonics - I Got Your Number.mp3 +C:/Users/Rik/Music/Artists/Stereophonics/Keep Calm and Carry On/Stereophonics - Innocent.mp3 +C:/Users/Rik/Music/Artists/Stereophonics/Keep Calm and Carry On/Stereophonics - Live 'N' Love.mp3 +C:/Users/Rik/Music/Artists/Stereophonics/Keep Calm and Carry On/Stereophonics - She's Alright.mp3 +C:/Users/Rik/Music/Artists/Stereophonics/Keep Calm and Carry On/Stereophonics - Show Me How.mp3 +C:/Users/Rik/Music/Artists/Stereophonics/Keep Calm and Carry On/Stereophonics - Stuck In A Rut.mp3 +C:/Users/Rik/Music/Artists/Stereophonics/Keep Calm and Carry On/Stereophonics - Trouble.mp3 +C:/Users/Rik/Music/Artists/Stereophonics/Keep Calm and Carry On/Stereophonics - Uppercut.mp3 +C:/Users/Rik/Music/Artists/Stereophonics/Keep Calm and Carry On/Stereophonics - Wonder.mp3 +C:/Users/Rik/Music/Artists/Foo Fighters/Greatest Hits/Foo Fighters - Everlong (Acoustic).mp3 +C:/Users/Rik/Music/Artists/Lifehouse/Smoke & Mirrors/Lifehouse - Everything (Live).mp3 +C:/Users/Rik/Music/Artists/Amber Pacific/Virtues/Amber Pacific - Forever.mp3 +C:/Users/Rik/Music/Artists/Blink-182/Neighborhoods/Blink-182 - After Midnight.mp3 +C:/Users/Rik/Music/Artists/Blink-182/Neighborhoods/Blink-182 - Even If She Falls.mp3 +C:/Users/Rik/Music/Artists/Blink-182/Neighborhoods/Blink-182 - Fighting the Gravity.mp3 +C:/Users/Rik/Music/Artists/Blink-182/Neighborhoods/Blink-182 - Ghost On The Dance Floor.mp3 +C:/Users/Rik/Music/Artists/Blink-182/Neighborhoods/Blink-182 - Heart's All Gone (Interlude).mp3 +C:/Users/Rik/Music/Artists/Blink-182/Neighborhoods/Blink-182 - Heart's All Gone.mp3 +C:/Users/Rik/Music/Artists/Blink-182/Neighborhoods/Blink-182 - Kaleidoscope.mp3 +C:/Users/Rik/Music/Artists/Blink-182/Neighborhoods/Blink-182 - Love Is Dangerous.mp3 +C:/Users/Rik/Music/Artists/Blink-182/Neighborhoods/Blink-182 - Mh 4.18.2011.mp3 +C:/Users/Rik/Music/Artists/Blink-182/Neighborhoods/Blink-182 - Natives.mp3 +C:/Users/Rik/Music/Artists/Blink-182/Neighborhoods/Blink-182 - Snake Charmer.mp3 +C:/Users/Rik/Music/Artists/Blink-182/Neighborhoods/Blink-182 - This Is Home.mp3 +C:/Users/Rik/Music/Artists/Blink-182/Neighborhoods/Blink-182 - Up All Night.mp3 +C:/Users/Rik/Music/Artists/Blink-182/Neighborhoods/Blink-182 - Wishing Well.mp3 +C:/Users/Rik/Music/Artists/Longwave/Secrets Are Sinister/Longwave - The Devil And The Liar.mp3 +C:/Users/Rik/Music/Artists/Kane/Singles Only/Kane - All I Can Do.mp3 +C:/Users/Rik/Music/Artists/Kane/Singles Only/Kane - Believe It.mp3 +C:/Users/Rik/Music/Artists/Kane/Singles Only/Kane - Can You Handle Me.mp3 +C:/Users/Rik/Music/Artists/Kane/Singles Only/Kane - Catwalk Criminal.mp3 +C:/Users/Rik/Music/Artists/Kane/Singles Only/Kane - Damn Those Eyes.mp3 +C:/Users/Rik/Music/Artists/Kane/Singles Only/Kane - Dreamer.mp3 +C:/Users/Rik/Music/Artists/Kane/Singles Only/Kane - Fearless.mp3 +C:/Users/Rik/Music/Artists/Kane/Singles Only/Kane - Hold On to the World.mp3 +C:/Users/Rik/Music/Artists/Kane/Singles Only/Kane - I Will Keep My Head Down.mp3 +C:/Users/Rik/Music/Artists/Kane/Singles Only/Kane - In Over My Head.mp3 +C:/Users/Rik/Music/Artists/Kane/Singles Only/Kane - It's London Calling.mp3 +C:/Users/Rik/Music/Artists/Kane/Singles Only/Kane - Let It Be.mp3 +C:/Users/Rik/Music/Artists/Kane/Singles Only/Kane - Love Over Healing.mp3 +C:/Users/Rik/Music/Artists/Kane/Singles Only/Kane - My Best Wasn't Good Enough.mp3 +C:/Users/Rik/Music/Artists/Kane/Singles Only/Kane - No Surrender.mp3 +C:/Users/Rik/Music/Artists/Kane/Singles Only/Kane - Rain Down On Me.mp3 +C:/Users/Rik/Music/Artists/Kane/Singles Only/Kane - Scream.mp3 +C:/Users/Rik/Music/Artists/Kane/Singles Only/Kane - Shot of a Gun.mp3 +C:/Users/Rik/Music/Artists/Kane/Singles Only/Kane - So Glad You Made It.mp3 +C:/Users/Rik/Music/Artists/Kane/Singles Only/Kane - Something to Say.mp3 +C:/Users/Rik/Music/Artists/Kane/Singles Only/Kane - Wanna Make It Happen.mp3 +C:/Users/Rik/Music/Artists/Kane/Singles Only/Kane - Where Do I Go Now.mp3 +C:/Users/Rik/Music/Artists/Coldplay/Mylo Xyloto/Coldplay - A Hopeful Transmission.mp3 +C:/Users/Rik/Music/Artists/Coldplay/Mylo Xyloto/Coldplay - Charlie Brown.mp3 +C:/Users/Rik/Music/Artists/Coldplay/Mylo Xyloto/Coldplay - Don't Let It Break Your Heart.mp3 +C:/Users/Rik/Music/Artists/Coldplay/Mylo Xyloto/Coldplay - Every Teardrop Is a Waterfall.mp3 +C:/Users/Rik/Music/Artists/Coldplay/Mylo Xyloto/Coldplay - Hurts Like Heaven.mp3 +C:/Users/Rik/Music/Artists/Coldplay/Mylo Xyloto/Coldplay - M.M.I.X..mp3 +C:/Users/Rik/Music/Artists/Coldplay/Mylo Xyloto/Coldplay - Major Minus.mp3 +C:/Users/Rik/Music/Artists/Coldplay/Mylo Xyloto/Coldplay - Mylo Xyloto.mp3 +C:/Users/Rik/Music/Artists/Coldplay/Mylo Xyloto/Coldplay - Paradise.mp3 +C:/Users/Rik/Music/Artists/Coldplay/Mylo Xyloto/Coldplay - Princess of China.mp3 +C:/Users/Rik/Music/Artists/Coldplay/Mylo Xyloto/Coldplay - U.F.O..mp3 +C:/Users/Rik/Music/Artists/Coldplay/Mylo Xyloto/Coldplay - Up in Flames.mp3 +C:/Users/Rik/Music/Artists/Coldplay/Mylo Xyloto/Coldplay - Up with the Birds.mp3 +C:/Users/Rik/Music/Artists/Coldplay/Mylo Xyloto/Coldplay - Us Against the World.mp3 +C:/Users/Rik/Music/Artists/Kane/Singles Only/Kane - High Places.mp3 +C:/Users/Rik/Music/Artists/White Lies/Ritual/White Lies - Bad Love.mp3 +C:/Users/Rik/Music/Artists/White Lies/Ritual/White Lies - Bigger Than Us.mp3 +C:/Users/Rik/Music/Artists/White Lies/Ritual/White Lies - Come Down.mp3 +C:/Users/Rik/Music/Artists/White Lies/Ritual/White Lies - Holy Ghost.mp3 +C:/Users/Rik/Music/Artists/White Lies/Ritual/White Lies - Is Love.mp3 +C:/Users/Rik/Music/Artists/White Lies/Ritual/White Lies - Peace & Quiet.mp3 +C:/Users/Rik/Music/Artists/White Lies/Ritual/White Lies - Strangers.mp3 +C:/Users/Rik/Music/Artists/White Lies/Ritual/White Lies - Streetlights.mp3 +C:/Users/Rik/Music/Artists/White Lies/Ritual/White Lies - The Power & The Glory.mp3 +C:/Users/Rik/Music/Artists/White Lies/Ritual/White Lies - Turn The Bells.mp3 +C:/Users/Rik/Music/Artists/Destine/Destine - Thousand Miles.mp3 +C:/Users/Rik/Music/Artists/The Seer/Heading for the Sun/The Seer - Dive Into The Blue Sky.mp3 +C:/Users/Rik/Music/Artists/The Seer/Heading for the Sun/The Seer - Eyes Gone Blind.mp3 +C:/Users/Rik/Music/Artists/The Seer/Heading for the Sun/The Seer - Fallen Leaves.mp3 +C:/Users/Rik/Music/Artists/The Seer/Heading for the Sun/The Seer - Rain Down On Me.mp3 +C:/Users/Rik/Music/Artists/The Seer/Heading for the Sun/The Seer - Raining.mp3 +C:/Users/Rik/Music/Artists/The Seer/Heading for the Sun/The Seer - Setting Sails.mp3 +C:/Users/Rik/Music/Artists/The Seer/Heading for the Sun/The Seer - The Borderline.mp3 +C:/Users/Rik/Music/Artists/The Seer/Heading for the Sun/The Seer - The Enemy.mp3 +C:/Users/Rik/Music/Artists/The Seer/Heading for the Sun/The Seer - Wasted.mp3 +C:/Users/Rik/Music/Artists/The Seer/Heading for the Sun/The Seer - What We Are.mp3 +C:/Users/Rik/Music/Artists/The Seer/Heading for the Sun/The Seer - Where Do We Go.mp3 +C:/Users/Rik/Music/Artists/The Seer/Heading for the Sun/The Seer - Wishful Thinking.mp3 +C:/Users/Rik/Music/Old/Bruce Springsteen/Bruce Springsteen - The River.mp3 +C:/Users/Rik/Music/Archive/Artists/Snow Patrol/Fallen Empires/Snow Patrol - Called Out In The Dark.mp3 +C:/Users/Rik/Music/Archive/Artists/Snow Patrol/Fallen Empires/Snow Patrol - This Isn't Everything You Are.mp3 +C:/Users/Rik/Music/Archive/Artists/The Wombats/This Modern Glitch/The Wombats - Techno Fan.mp3 +C:/Users/Rik/Music/Archive/Artists/The Wombats/This Modern Glitch/The Wombats - Tokyo (Vampires & Wolves).mp3 +C:/Users/Rik/Music/Artists/The Offspring/Rise and Fall Rage and Grace/The Offspring - A Lot Like Me.mp3 +C:/Users/Rik/Music/Artists/The Offspring/Rise and Fall Rage and Grace/The Offspring - Fix You.mp3 +C:/Users/Rik/Music/Artists/The Offspring/Rise and Fall Rage and Grace/The Offspring - Half-Truism.mp3 +C:/Users/Rik/Music/Artists/The Offspring/Rise and Fall Rage and Grace/The Offspring - Hammerhead.mp3 +C:/Users/Rik/Music/Artists/The Offspring/Rise and Fall Rage and Grace/The Offspring - Kristy, Are You Doing Okay.mp3 +C:/Users/Rik/Music/Artists/The Offspring/Rise and Fall Rage and Grace/The Offspring - Let's Hear It For Rock Bottom.mp3 +C:/Users/Rik/Music/Artists/The Offspring/Rise and Fall Rage and Grace/The Offspring - Nothingtown.mp3 +C:/Users/Rik/Music/Artists/The Offspring/Rise and Fall Rage and Grace/The Offspring - O.C. Life.mp3 +C:/Users/Rik/Music/Artists/The Offspring/Rise and Fall Rage and Grace/The Offspring - Rise And Fall.mp3 +C:/Users/Rik/Music/Artists/The Offspring/Rise and Fall Rage and Grace/The Offspring - Stuff Is Messed Up.mp3 +C:/Users/Rik/Music/Artists/The Offspring/Rise and Fall Rage and Grace/The Offspring - Takes Me Nowhere.mp3 +C:/Users/Rik/Music/Artists/The Offspring/Rise and Fall Rage and Grace/The Offspring - Trust In You.mp3 +C:/Users/Rik/Music/Artists/The Offspring/Rise and Fall Rage and Grace/The Offspring - You're Gonna Go Far, Kid.mp3 +C:/Users/Rik/Music/Artists/Nickelback/Here and Now/Nickelback - Bottoms Up.mp3 +C:/Users/Rik/Music/Artists/Nickelback/Here and Now/Nickelback - Don't Ever Let It End.mp3 +C:/Users/Rik/Music/Artists/Nickelback/Here and Now/Nickelback - Everything I Wanna Do.mp3 +C:/Users/Rik/Music/Artists/Nickelback/Here and Now/Nickelback - Gotta Get Me Some.mp3 +C:/Users/Rik/Music/Artists/Nickelback/Here and Now/Nickelback - Holding On to Heaven.mp3 +C:/Users/Rik/Music/Artists/Nickelback/Here and Now/Nickelback - Kiss It Goodbye.mp3 +C:/Users/Rik/Music/Artists/Nickelback/Here and Now/Nickelback - Lullaby.mp3 +C:/Users/Rik/Music/Artists/Nickelback/Here and Now/Nickelback - Midnight Queen.mp3 +C:/Users/Rik/Music/Artists/Nickelback/Here and Now/Nickelback - This Means War.mp3 +C:/Users/Rik/Music/Artists/Nickelback/Here and Now/Nickelback - Trying Not to Love You.mp3 +C:/Users/Rik/Music/Artists/Nickelback/Here and Now/Nickelback - When We Stand Together.mp3 +C:/Users/Rik/Music/Artists/The Vaccines/What Did You Expect From The Vaccines/The Vaccines - A Lack of Understanding.mp3 +C:/Users/Rik/Music/Artists/The Vaccines/What Did You Expect From The Vaccines/The Vaccines - All in White.mp3 +C:/Users/Rik/Music/Artists/The Vaccines/What Did You Expect From The Vaccines/The Vaccines - Blow It Up.mp3 +C:/Users/Rik/Music/Artists/The Vaccines/What Did You Expect From The Vaccines/The Vaccines - Family Friend.mp3 +C:/Users/Rik/Music/Artists/The Vaccines/What Did You Expect From The Vaccines/The Vaccines - If You Wanna.mp3 +C:/Users/Rik/Music/Artists/The Vaccines/What Did You Expect From The Vaccines/The Vaccines - N%C3%B8rgaard.mp3 +C:/Users/Rik/Music/Artists/The Vaccines/What Did You Expect From The Vaccines/The Vaccines - Post Break-Up Sex.mp3 +C:/Users/Rik/Music/Artists/The Vaccines/What Did You Expect From The Vaccines/The Vaccines - Under Your Thumb.mp3 +C:/Users/Rik/Music/Artists/The Vaccines/What Did You Expect From The Vaccines/The Vaccines - Westsuit.mp3 +C:/Users/Rik/Music/Artists/The Vaccines/What Did You Expect From The Vaccines/The Vaccines - Wolf Pack.mp3 +C:/Users/Rik/Music/Artists/The Vaccines/What Did You Expect From The Vaccines/The Vaccines - Wreckin' Bar.mp3 +C:/Users/Rik/Music/Artists/Daughtry/Leave This Town/Daughtry - Call Your Name.mp3 +C:/Users/Rik/Music/Artists/Daughtry/Leave This Town/Daughtry - Every Time You Turn Around.mp3 +C:/Users/Rik/Music/Artists/Daughtry/Leave This Town/Daughtry - Ghost Of Me.mp3 +C:/Users/Rik/Music/Artists/Daughtry/Leave This Town/Daughtry - Learn My Lesson.mp3 +C:/Users/Rik/Music/Artists/Daughtry/Leave This Town/Daughtry - Life After You.mp3 +C:/Users/Rik/Music/Artists/Daughtry/Leave This Town/Daughtry - No Surprise.mp3 +C:/Users/Rik/Music/Artists/Daughtry/Leave This Town/Daughtry - Open Up Your Eyes.mp3 +C:/Users/Rik/Music/Artists/Daughtry/Leave This Town/Daughtry - September.mp3 +C:/Users/Rik/Music/Artists/Daughtry/Leave This Town/Daughtry - Supernatural.mp3 +C:/Users/Rik/Music/Artists/Daughtry/Leave This Town/Daughtry - Tennessee Line.mp3 +C:/Users/Rik/Music/Artists/Daughtry/Leave This Town/Daughtry - What I Meant To Say.mp3 +C:/Users/Rik/Music/Artists/Daughtry/Leave This Town/Daughtry - You Don't Belong.mp3 +C:/Users/Rik/Music/Artists/Moke/The Long & Dangerous Sea/Moke - Black And Blue.mp3 +C:/Users/Rik/Music/Artists/Moke/The Long & Dangerous Sea/Moke - Ghost.mp3 +C:/Users/Rik/Music/Artists/Moke/The Long & Dangerous Sea/Moke - Heaven.mp3 +C:/Users/Rik/Music/Artists/Moke/The Long & Dangerous Sea/Moke - Lament.mp3 +C:/Users/Rik/Music/Artists/Moke/The Long & Dangerous Sea/Moke - Love My Life.mp3 +C:/Users/Rik/Music/Artists/Moke/The Long & Dangerous Sea/Moke - Nobody's Listening.mp3 +C:/Users/Rik/Music/Artists/Moke/The Long & Dangerous Sea/Moke - Switch.mp3 +C:/Users/Rik/Music/Artists/Moke/The Long & Dangerous Sea/Moke - Terrible End.mp3 +C:/Users/Rik/Music/Artists/Moke/The Long & Dangerous Sea/Moke - The Long & Dangerous Sea.mp3 +C:/Users/Rik/Music/Artists/Moke/The Long & Dangerous Sea/Moke - Windows Of Hope.mp3 +C:/Users/Rik/Music/Artists/Placebo/Battle for the Sun/Placebo - Ashtray Heart.mp3 +C:/Users/Rik/Music/Artists/Placebo/Battle for the Sun/Placebo - Battle for the Sun.mp3 +C:/Users/Rik/Music/Artists/Placebo/Battle for the Sun/Placebo - Breathe Underwater.mp3 +C:/Users/Rik/Music/Artists/Placebo/Battle for the Sun/Placebo - Bright Lights.mp3 +C:/Users/Rik/Music/Artists/Placebo/Battle for the Sun/Placebo - Come Undone.mp3 +C:/Users/Rik/Music/Artists/Placebo/Battle for the Sun/Placebo - Devil in the Details.mp3 +C:/Users/Rik/Music/Artists/Placebo/Battle for the Sun/Placebo - For What It's Worth.mp3 +C:/Users/Rik/Music/Artists/Placebo/Battle for the Sun/Placebo - Happy You're Gone.mp3 +C:/Users/Rik/Music/Artists/Placebo/Battle for the Sun/Placebo - Julien.mp3 +C:/Users/Rik/Music/Artists/Placebo/Battle for the Sun/Placebo - Kings of Medicine.mp3 +C:/Users/Rik/Music/Artists/Placebo/Battle for the Sun/Placebo - Kitty Litter.mp3 +C:/Users/Rik/Music/Artists/Placebo/Battle for the Sun/Placebo - Speak in Tongues.mp3 +C:/Users/Rik/Music/Artists/Placebo/Battle for the Sun/Placebo - The Never-Ending Why.mp3 +C:/Users/Rik/Music/Artists/Keane/Night Train/Keane - Back In Time.mp3 +C:/Users/Rik/Music/Artists/Keane/Night Train/Keane - Clear Skies.mp3 +C:/Users/Rik/Music/Artists/Keane/Night Train/Keane - House Lights.mp3 +C:/Users/Rik/Music/Artists/Keane/Night Train/Keane - Ishin Denshin (You've Got To Help Yourself).mp3 +C:/Users/Rik/Music/Artists/Keane/Night Train/Keane - Looking Back.mp3 +C:/Users/Rik/Music/Artists/Keane/Night Train/Keane - My Shadow.mp3 +C:/Users/Rik/Music/Artists/Keane/Night Train/Keane - Stop For a Minute.mp3 +C:/Users/Rik/Music/Artists/Keane/Night Train/Keane - Your Love.mp3 +C:/Users/Rik/Music/Artists/Keane/Under The Iron Sea/Keane - A Bad Dream.mp3 +C:/Users/Rik/Music/Artists/Keane/Under The Iron Sea/Keane - Atlantic.mp3 +C:/Users/Rik/Music/Artists/Keane/Under The Iron Sea/Keane - Broken Toy.mp3 +C:/Users/Rik/Music/Artists/Keane/Under The Iron Sea/Keane - Crystal Ball.mp3 +C:/Users/Rik/Music/Artists/Keane/Under The Iron Sea/Keane - Hamburg Song.mp3 +C:/Users/Rik/Music/Artists/Keane/Under The Iron Sea/Keane - Is It Any Wonder.mp3 +C:/Users/Rik/Music/Artists/Keane/Under The Iron Sea/Keane - Leaving So Soon.mp3 +C:/Users/Rik/Music/Artists/Keane/Under The Iron Sea/Keane - Let It Slide .mp3 +C:/Users/Rik/Music/Artists/Keane/Under The Iron Sea/Keane - Nothing In My Way.mp3 +C:/Users/Rik/Music/Artists/Keane/Under The Iron Sea/Keane - Put It Behind You.mp3 +C:/Users/Rik/Music/Artists/Keane/Under The Iron Sea/Keane - The Frog Prince.mp3 +C:/Users/Rik/Music/Artists/Keane/Under The Iron Sea/Keane - The Iron Sea.mp3 +C:/Users/Rik/Music/Artists/Keane/Under The Iron Sea/Keane - Try Again.mp3 +C:/Users/Rik/Music/Artists/Hey Monday/Hold On Tight/Hey Monday - 6 Months.mp3 +C:/Users/Rik/Music/Artists/Hey Monday/Hold On Tight/Hey Monday - Arizona.mp3 +C:/Users/Rik/Music/Artists/Hey Monday/Hold On Tight/Hey Monday - Candles.mp3 +C:/Users/Rik/Music/Artists/Hey Monday/Hold On Tight/Hey Monday - Homecoming.mp3 +C:/Users/Rik/Music/Artists/Hey Monday/Hold On Tight/Hey Monday - How You Love Me Now.mp3 +C:/Users/Rik/Music/Artists/Hey Monday/Hold On Tight/Hey Monday - Hurricane Streets.mp3 +C:/Users/Rik/Music/Artists/Hey Monday/Hold On Tight/Hey Monday - Josey.mp3 +C:/Users/Rik/Music/Artists/Hey Monday/Hold On Tight/Hey Monday - Obvious.mp3 +C:/Users/Rik/Music/Artists/Hey Monday/Hold On Tight/Hey Monday - Run, Don't Walk.mp3 +C:/Users/Rik/Music/Artists/Hey Monday/Hold On Tight/Hey Monday - Set Off.mp3 +C:/Users/Rik/Music/Artists/Hey Monday/Hold On Tight/Hey Monday - Should've Tried Harder.mp3 +C:/Users/Rik/Music/Artists/Mae/The Everglow/Mae - Anything.mp3 +C:/Users/Rik/Music/Artists/Mae/The Everglow/Mae - Breakdown.mp3 +C:/Users/Rik/Music/Artists/Mae/The Everglow/Mae - Cover Me.mp3 +C:/Users/Rik/Music/Artists/Mae/The Everglow/Mae - Epilogue.mp3 +C:/Users/Rik/Music/Artists/Mae/The Everglow/Mae - Mistakes we Knew we Were Making.mp3 +C:/Users/Rik/Music/Artists/Mae/The Everglow/Mae - Painless.mp3 +C:/Users/Rik/Music/Artists/Mae/The Everglow/Mae - Prologue.mp3 +C:/Users/Rik/Music/Artists/Mae/The Everglow/Mae - Ready and Waiting to Fall.mp3 +C:/Users/Rik/Music/Artists/Mae/The Everglow/Mae - Someone Else's Arms.mp3 +C:/Users/Rik/Music/Artists/Mae/The Everglow/Mae - Suspension.mp3 +C:/Users/Rik/Music/Artists/Mae/The Everglow/Mae - The Everglow.mp3 +C:/Users/Rik/Music/Artists/Mae/The Everglow/Mae - The Ocean.mp3 +C:/Users/Rik/Music/Artists/Mae/The Everglow/Mae - The Sun and the Moon.mp3 +C:/Users/Rik/Music/Artists/Mae/The Everglow/Mae - This is the Countdown.mp3 +C:/Users/Rik/Music/Artists/Mae/The Everglow/Mae - We're So Far Away.mp3 +C:/Users/Rik/Music/Artists/Saves the Day/Saves the Day - All I'm Losing Is Me.mp3 +C:/Users/Rik/Music/Artists/Saves the Day/Saves the Day - At Your Funeral.mp3 +C:/Users/Rik/Music/Artists/Saves the Day/Saves the Day - Cars And Calories.mp3 +C:/Users/Rik/Music/Artists/Saves the Day/Saves the Day - Certain Tragedy.mp3 +C:/Users/Rik/Music/Artists/Saves the Day/Saves the Day - Firefly.mp3 +C:/Users/Rik/Music/Artists/Saves the Day/Saves the Day - Freakish.mp3 +C:/Users/Rik/Music/Artists/Saves the Day/Saves the Day - Jukebox Breakdown.mp3 +C:/Users/Rik/Music/Artists/Saves the Day/Saves the Day - Nightingale.mp3 +C:/Users/Rik/Music/Artists/Saves the Day/Saves the Day - See You.mp3 +C:/Users/Rik/Music/Artists/Saves the Day/Saves the Day - This Is Not An Exit.mp3 +C:/Users/Rik/Music/Artists/Saves the Day/Saves the Day - Your Ghost Takes Flight.mp3 \ No newline at end of file diff --git a/java/txt/options b/java/txt/options new file mode 100644 index 0000000..4d95aae --- /dev/null +++ b/java/txt/options @@ -0,0 +1,182 @@ +LAME 32bits version 3.98.4 (http://www.mp3dev.org/) + +usage: lame [options] [outfile] + + and/or can be "-", which means stdin/stdout. + +RECOMMENDED: + lame -V2 input.wav output.mp3 + +OPTIONS: + Input options: + --scale scale input (multiply PCM data) by + --scale-l scale channel 0 (left) input (multiply PCM data) by + --scale-r scale channel 1 (right) input (multiply PCM data) by + --mp1input input file is a MPEG Layer I file + --mp2input input file is a MPEG Layer II file + --mp3input input file is a MPEG Layer III file + --nogap <...> + gapless encoding for a set of contiguous files + --nogapout + output dir for gapless encoding (must precede --nogap) + --nogaptags allow the use of VBR tags in gapless encoding + + Input options for RAW PCM: + -r input is raw pcm + -x force byte-swapping of input + -s sfreq sampling frequency of input file (kHz) - default 44.1 kHz + --bitwidth w input bit width is w (default 16) + --signed input is signed (default) + --unsigned input is unsigned + --little-endian input is little-endian (default) + --big-endian input is big-endian + + + Operational options: + -a downmix from stereo to mono file for mono encoding + -m (j)oint, (s)imple, (f)orce, (d)dual-mono, (m)ono + default is (j) or (s) depending on bitrate + joint = joins the best possible of MS and LR stereo + simple = force LR stereo on all frames + force = force MS stereo on all frames. + --preset type type must be "medium", "standard", "extreme", "insane", + or a value for an average desired bitrate and depending + on the value specified, appropriate quality settings will + be used. + "--preset help" gives more info on these + --comp choose bitrate to achive a compression ratio of + --replaygain-fast compute RG fast but slightly inaccurately (default) + --replaygain-accurate compute RG more accurately and find the peak sample + --noreplaygain disable ReplayGain analysis + --clipdetect enable --replaygain-accurate and print a message whether + clipping occurs and how far the waveform is from full scale + --flush flush output stream as soon as possible + --freeformat produce a free format bitstream + --decode input=mp3 file, output=wav + -t disable writing wav header when using --decode + + + Verbosity: + --disptime print progress report every arg seconds + -S don't print progress report, VBR histograms + --nohist disable VBR histogram display + --silent don't print anything on screen + --quiet don't print anything on screen + --brief print more useful information + --verbose print a lot of useful information + + Noise shaping & psycho acoustic algorithms: + -q = 0...9. Default -q 5 + -q 0: Highest quality, very slow + -q 9: Poor quality, but fast + -h Same as -q 2. Recommended. + -f Same as -q 7. Fast, ok quality + + + CBR (constant bitrate, the default) options: + -b set the bitrate in kbps, default 128 kbps + --cbr enforce use of constant bitrate + + ABR options: + --abr specify average bitrate desired (instead of quality) + + VBR options: + -V n quality setting for VBR. default n=4 + 0=high quality,bigger files. 9=smaller files + -v the same as -V 4 + --vbr-old use old variable bitrate (VBR) routine + --vbr-new use new variable bitrate (VBR) routine (default) + -b specify minimum allowed bitrate, default 32 kbps + -B specify maximum allowed bitrate, default 320 kbps + -F strictly enforce the -b option, for use with players that + do not support low bitrate mp3 + -t disable writing LAME Tag + -T enable and force writing LAME Tag + + + PSY related: + --temporal-masking x x=0 disables, x=1 enables temporal masking effect + --nssafejoint M/S switching criterion + --nsmsfix M/S switching tuning [effective 0-3.5] + --interch x adjust inter-channel masking ratio + --ns-bass x adjust masking for sfbs 0 - 6 (long) 0 - 5 (short) + --ns-alto x adjust masking for sfbs 7 - 13 (long) 6 - 10 (short) + --ns-treble x adjust masking for sfbs 14 - 21 (long) 11 - 12 (short) + --ns-sfb21 x change ns-treble by x dB for sfb21 + + + experimental switches: + -Y lets LAME ignore noise in sfb21, like in CBR + + + MP3 header/stream options: + -e de-emphasis n/5/c (obsolete) + -c mark as copyright + -o mark as non-original + -p error protection. adds 16 bit checksum to every frame + (the checksum is computed correctly) + --nores disable the bit reservoir + --strictly-enforce-ISO comply as much as possible to ISO MPEG spec + + Filter options: + --lowpass frequency(kHz), lowpass filter cutoff above freq + --lowpass-width frequency(kHz) - default 15% of lowpass freq + --highpass frequency(kHz), highpass filter cutoff below freq + --highpass-width frequency(kHz) - default 15% of highpass freq + --resample sampling frequency of output file(kHz)- default=automatic + + + ID3 tag options: + --tt audio/song title (max 30 chars for version 1 tag) + --ta <artist> audio/song artist (max 30 chars for version 1 tag) + --tl <album> audio/song album (max 30 chars for version 1 tag) + --ty <year> audio/song year of issue (1 to 9999) + --tc <comment> user-defined text (max 30 chars for v1 tag, 28 for v1.1) + --tn <track[/total]> audio/song track number and (optionally) the total + number of tracks on the original recording. (track + and total each 1 to 255. just the track number + creates v1.1 tag, providing a total forces v2.0). + --tg <genre> audio/song genre (name or number in list) + --ti <file> audio/song albumArt (jpeg/png/gif file, 128KB max, v2.3) + --tv <id=value> user-defined frame specified by id and value (v2.3 tag) + --add-id3v2 force addition of version 2 tag + --id3v1-only add only a version 1 tag + --id3v2-only add only a version 2 tag + --space-id3v1 pad version 1 tag with spaces instead of nulls + --pad-id3v2 same as '--pad-id3v2-size 128' + --pad-id3v2-size <value> adds version 2 tag, pad with extra <value> bytes + --genre-list print alphabetically sorted ID3 genre list and exit + --ignore-tag-errors ignore errors in values passed for tags + + Note: A version 2 tag will NOT be added unless one of the input fields + won't fit in a version 1 tag (e.g. the title string is longer than 30 + characters), or the '--add-id3v2' or '--id3v2-only' options are used, + or output is redirected to stdout. + + +MS-Windows-specific options: + --priority <type> sets the process priority: + 0,1 = Low priority (IDLE_PRIORITY_CLASS) + 2 = normal priority (NORMAL_PRIORITY_CLASS, default) + 3,4 = High priority (HIGH_PRIORITY_CLASS)) + Note: Calling '--priority' without a parameter will select priority 0. + +Misc: + --license print License information + + + + Platform specific: + --noasm <instructions> disable assembly optimizations for mmx/3dnow/sse + + + +MPEG-1 layer III sample frequencies (kHz): 32 48 44.1 +bitrates (kbps): 32 40 48 56 64 80 96 112 128 160 192 224 256 320 + +MPEG-2 layer III sample frequencies (kHz): 16 24 22.05 +bitrates (kbps): 8 16 24 32 40 48 56 64 80 96 112 128 144 160 + +MPEG-2.5 layer III sample frequencies (kHz): 8 12 11.025 +bitrates (kbps): 8 16 24 32 40 48 56 64 + diff --git a/java/txt/short b/java/txt/short new file mode 100644 index 0000000..538d3ff --- /dev/null +++ b/java/txt/short @@ -0,0 +1 @@ +medium.mp3 \ No newline at end of file diff --git a/java/txt/testfiles.txt b/java/txt/testfiles.txt new file mode 100644 index 0000000..6c2c2b6 --- /dev/null +++ b/java/txt/testfiles.txt @@ -0,0 +1,12 @@ +junk (with or without header) +PCM_SIGNED 8000.0 Hz, 16 bit, mono, 2 bytes/frame, little-endian +-r 8k -t s16 -c 1 -e signed-integer + + +out (without header) +PCM_SIGNED 8000.0 Hz, 16 bit, stereo, 4 bytes/frame, big-endian +-r 128k -t s32 -c 2 -2 signed integer [reasonable] + +out (without header) +PCM_SIGNED 192000.0 Hz, 16 bit, stereo, 4 bytes/frame, little-endian +-r 192k -t s16 -c 2 [-e signed-integer] \ No newline at end of file diff --git a/wget.exe b/java/wget.exe similarity index 100% rename from wget.exe rename to java/wget.exe diff --git a/zlib1.dll b/java/zlib1.dll similarity index 100% rename from zlib1.dll rename to java/zlib1.dll