diff --git a/.gitignore b/.gitignore
index 83226d8..f3ff31b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,4 +2,8 @@ bin
.gradle
.settings
build
+<<<<<<< HEAD
+/cpp/pipe/Release/src
+=======
src
+>>>>>>> 1b005c69f5ba5b443ef5addc6aad13236196f3dc
diff --git a/cpp/pipe/.cproject b/cpp/pipe/.cproject
new file mode 100644
index 0000000..612ccc7
--- /dev/null
+++ b/cpp/pipe/.cproject
@@ -0,0 +1,152 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/cpp/pipe/.project b/cpp/pipe/.project
new file mode 100644
index 0000000..a14c5b2
--- /dev/null
+++ b/cpp/pipe/.project
@@ -0,0 +1,27 @@
+
+
+ cpp.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/Debug/copy.bat b/cpp/pipe/Debug/copy.bat
new file mode 100644
index 0000000..2f38e77
--- /dev/null
+++ b/cpp/pipe/Debug/copy.bat
@@ -0,0 +1 @@
+copy pipe.dll ..\..\..\java\sound\pipe.dll
\ No newline at end of file
diff --git a/cpp/pipe/Release/copy.bat b/cpp/pipe/Release/copy.bat
new file mode 100644
index 0000000..2f38e77
--- /dev/null
+++ b/cpp/pipe/Release/copy.bat
@@ -0,0 +1 @@
+copy pipe.dll ..\..\..\java\sound\pipe.dll
\ No newline at end of file
diff --git a/cpp/pipe/Release/pipe.dll b/cpp/pipe/Release/pipe.dll
new file mode 100644
index 0000000..c698219
Binary files /dev/null and b/cpp/pipe/Release/pipe.dll differ
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..1a35caa
--- /dev/null
+++ b/cpp/pipe/src/pipe.c
@@ -0,0 +1,192 @@
+#include
+#include
+#include
+#include "pipe.h"
+
+#define DEBUG 0
+
+JNIEXPORT jint JNICALL Java_pipe_Pipe_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_Pipe_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_Pipe_GetLastError(JNIEnv *env,
+ jclass className) {
+ DWORD errorNumber = GetLastError();
+ return (jint) errorNumber;
+}
+
+JNIEXPORT jboolean JNICALL Java_pipe_Pipe_CloseHandle(JNIEnv *env,
+ jclass className, jint hNamedPipe) {
+ BOOL result;
+ HANDLE pipeHandler = (HANDLE) hNamedPipe;
+ result = CloseHandle(pipeHandler);
+ return result;
+}
+
+JNIEXPORT jbyteArray JNICALL Java_pipe_Pipe_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_Pipe_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_Pipe_FlushFileBuffers(JNIEnv *env,
+ jclass className, jint hNamedPipe) {
+ BOOL result;
+ HANDLE pipeHandler = (HANDLE) hNamedPipe;
+ result = FlushFileBuffers(pipeHandler);
+ return result;
+}
+
+JNIEXPORT jboolean JNICALL Java_pipe_Pipe_DisconnectNamedPipe(JNIEnv *env,
+ jclass className, jint hNamedPipe) {
+ BOOL result;
+ HANDLE pipeHandler = (HANDLE) hNamedPipe;
+ result = DisconnectNamedPipe(pipeHandler);
+ return result;
+}
+
+JNIEXPORT jint JNICALL Java_pipe_Pipe_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_Pipe_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_Pipe_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_Pipe_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..af398cb
--- /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_Pipe_CreateNamedPipe
+ (JNIEnv *, jclass, jstring, jint, jint, jint, jint, jint, jint, jint);
+
+/*
+ * Class: Pipes
+ * Method: ConnectNamedPipe
+ * Signature: (II)Z
+ */
+JNIEXPORT jboolean JNICALL Java_pipe_Pipe_ConnectNamedPipe
+ (JNIEnv *, jclass, jint, jint);
+
+/*
+ * Class: Pipes
+ * Method: GetLastError
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_pipe_Pipe_GetLastError
+ (JNIEnv *, jclass);
+
+/*
+ * Class: Pipes
+ * Method: CloseHandle
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_pipe_Pipe_CloseHandle
+ (JNIEnv *, jclass, jint);
+
+/*
+ * Class: Pipes
+ * Method: ReadFile
+ * Signature: (II)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_pipe_Pipe_ReadFile
+ (JNIEnv *, jclass, jint, jint);
+
+/*
+ * Class: Pipes
+ * Method: WriteFile
+ * Signature: (I[BI)I
+ */
+JNIEXPORT jint JNICALL Java_pipe_Pipe_WriteFile
+ (JNIEnv *, jclass, jint, jbyteArray, jint);
+
+/*
+ * Class: Pipes
+ * Method: FlushFileBuffers
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_pipe_Pipe_FlushFileBuffers
+ (JNIEnv *, jclass, jint);
+
+/*
+ * Class: Pipes
+ * Method: DisconnectNamedPipe
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL Java_pipe_Pipe_DisconnectNamedPipe
+ (JNIEnv *, jclass, jint);
+
+/*
+ * Class: Pipes
+ * Method: CreateFile
+ * Signature: (Ljava/lang/String;IIIIII)I
+ */
+JNIEXPORT jint JNICALL Java_pipe_Pipe_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_Pipe_WaitNamedPipe
+ (JNIEnv *, jclass, jstring, jint);
+
+/*
+ * Class: Pipes
+ * Method: FormatMessage
+ * Signature: (I)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_pipe_Pipe_FormatMessage
+ (JNIEnv *, jclass, jint);
+
+/*
+ * Class: Pipes
+ * Method: Print
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_pipe_Pipe_Print
+ (JNIEnv *, jclass, jstring);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/java/pipe.dll b/java/pipe.dll
new file mode 100644
index 0000000..f0ee87e
Binary files /dev/null and b/java/pipe.dll differ
diff --git a/java/settings.gradle b/java/settings.gradle
index 64c3439..7d41c41 100644
--- a/java/settings.gradle
+++ b/java/settings.gradle
@@ -1 +1 @@
-include "base", "mimis", "wiiusej", "wiigee", "itunescontroller"
\ No newline at end of file
+include "base", "mimis", "wiiusej", "wiigee", "itunescontroller", "sound"
\ No newline at end of file
diff --git a/java/sound/.classpath b/java/sound/.classpath
new file mode 100644
index 0000000..4828d2a
--- /dev/null
+++ b/java/sound/.classpath
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/java/sound/.gitignore b/java/sound/.gitignore
new file mode 100644
index 0000000..a4bf388
--- /dev/null
+++ b/java/sound/.gitignore
@@ -0,0 +1,3 @@
+/bin
+/.settings
+/sound
diff --git a/java/sound/.project b/java/sound/.project
new file mode 100644
index 0000000..87072b8
--- /dev/null
+++ b/java/sound/.project
@@ -0,0 +1,18 @@
+
+
+ java.sound
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.springsource.ide.eclipse.gradle.core.nature
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/java/sound/build.gradle b/java/sound/build.gradle
new file mode 100644
index 0000000..c758e85
--- /dev/null
+++ b/java/sound/build.gradle
@@ -0,0 +1,12 @@
+dependencies {
+ compile project(':base')
+
+ compile 'commons-io:commons-io:2.+'
+ compile 'commons-cli:commons-cli:1.+'
+ compile 'commons-pool:commons-pool:1.+'
+ compile 'org.slf4j:slf4j-api:1.+'
+ compile 'org.slf4j:slf4j-log4j12:1.7.5'
+ compile 'org.ostermiller:utils:1.+'
+ compile 'com.googlecode.soundlibs:jlayer:1.+'
+ compile 'net.sf.javamusictag:jid3lib:0.+'
+}
\ No newline at end of file
diff --git a/java/sound/build.xml b/java/sound/build.xml
new file mode 100644
index 0000000..dbf0eb1
--- /dev/null
+++ b/java/sound/build.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/java/sound/lame.exe b/java/sound/lame.exe
new file mode 100644
index 0000000..7e69522
Binary files /dev/null and b/java/sound/lame.exe differ
diff --git a/java/sound/launch4j.xml b/java/sound/launch4j.xml
new file mode 100644
index 0000000..548e148
--- /dev/null
+++ b/java/sound/launch4j.xml
@@ -0,0 +1,22 @@
+
+ false
+ gui
+ stream.jar
+ stream.exe
+
+
+
+ normal
+ http://java.com/download
+
+ false
+ false
+
+
+
+
+ 1.6.0
+
+ preferJre
+
+
\ No newline at end of file
diff --git a/java/sound/libgomp-1.dll b/java/sound/libgomp-1.dll
new file mode 100644
index 0000000..f4afc3e
Binary files /dev/null and b/java/sound/libgomp-1.dll differ
diff --git a/java/sound/libmad.dll b/java/sound/libmad.dll
new file mode 100644
index 0000000..98730c5
Binary files /dev/null and b/java/sound/libmad.dll differ
diff --git a/java/sound/libmp3lame.dll b/java/sound/libmp3lame.dll
new file mode 100644
index 0000000..719126b
Binary files /dev/null and b/java/sound/libmp3lame.dll differ
diff --git a/java/sound/pipe.dll b/java/sound/pipe.dll
new file mode 100644
index 0000000..8a948e6
Binary files /dev/null and b/java/sound/pipe.dll differ
diff --git a/java/sound/play.exe b/java/sound/play.exe
new file mode 100644
index 0000000..e3382ea
Binary files /dev/null and b/java/sound/play.exe differ
diff --git a/java/sound/pthreadgc2.dll b/java/sound/pthreadgc2.dll
new file mode 100644
index 0000000..f64cc52
Binary files /dev/null and b/java/sound/pthreadgc2.dll differ
diff --git a/java/sound/sox.exe b/java/sound/sox.exe
new file mode 100644
index 0000000..e3382ea
Binary files /dev/null and b/java/sound/sox.exe differ
diff --git a/java/sound/soxi.exe b/java/sound/soxi.exe
new file mode 100644
index 0000000..e3382ea
Binary files /dev/null and b/java/sound/soxi.exe differ
diff --git a/java/sound/src/main/java/old/Converter.java b/java/sound/src/main/java/old/Converter.java
new file mode 100644
index 0000000..ab6f405
--- /dev/null
+++ b/java/sound/src/main/java/old/Converter.java
@@ -0,0 +1,187 @@
+package old;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import sound.util.Utils;
+import javazoom.jl.decoder.Bitstream;
+import javazoom.jl.decoder.BitstreamException;
+import base.exception.worker.ActivateException;
+import base.exception.worker.DeactivateException;
+import base.worker.Worker;
+
+import com.Ostermiller.util.CircularByteBuffer;
+
+public class Converter extends Worker {
+ public static final String COMMAND = "lame --mp3input --cbr %s - - --quiet";
+ public static final int BYTES = 4096; // bytes
+ public static final int BUFFER = 30000; // milliseconds
+ public static final int BUFFERING = 1000; // milliseconds
+
+ protected int targetRate;
+ protected int rate;
+ protected int buffer;
+ protected boolean convert;
+
+ protected Process process;
+ protected InputStream sourceInputStream, processInputStream, inputStream;
+ protected OutputStream processOutputStream;
+ protected CircularByteBuffer circularByteBuffer;
+ protected BufferWorker bufferWorker;
+
+ public Converter(InputStream inputStream) {
+ this(inputStream, -1);
+ }
+
+ public Converter(InputStream inputStream, int targetRate) {
+ this.sourceInputStream = inputStream;
+ this.targetRate = targetRate;
+ bufferWorker = new BufferWorker();
+ convert = false;
+ }
+
+ public void exit() {
+ super.exit();
+ bufferWorker.exit();
+ }
+
+ public synchronized void activate() throws ActivateException {
+ /* Read bitrate */
+ BufferedInputStream bufferedInputStream = new BufferedInputStream(sourceInputStream);
+ Bitstream bitStream = new Bitstream(bufferedInputStream);
+ try {
+ rate = bitStream.readFrame().bitrate() / 1000;
+ buffer = BUFFER * rate / 8;
+ } catch (BitstreamException e) {
+ logger.error("", e);
+ throw new ActivateException();
+ }
+
+ /* Check for need to convert */
+ if (targetRate < 0 || rate == targetRate) {
+ logger.debug("No conversion required");
+ inputStream = sourceInputStream;
+ } else {
+ logger.debug("Converting from " + rate + "kbps to " + targetRate + "kbps");
+ try {
+ String command = String.format(COMMAND, rate > targetRate ? "-B " + targetRate : "-F -b " + targetRate);
+ logger.debug("Starting process: " + command);
+ process = Runtime.getRuntime().exec(command);
+ processInputStream = process.getInputStream();
+ processOutputStream = process.getOutputStream();
+
+ /* Buffer output */
+ circularByteBuffer = new CircularByteBuffer(CircularByteBuffer.INFINITE_SIZE);
+ inputStream = circularByteBuffer.getInputStream();
+ bufferWorker.start();
+ convert = true;
+ } catch (IOException e) {
+ logger.error("", e);
+ throw new ActivateException();
+ }
+ }
+ super.activate();
+ notifyAll();
+ }
+
+ protected void deactivate() throws DeactivateException {
+ super.deactivate();
+ try {
+ sourceInputStream.close();
+ bufferWorker.stop();
+ if (convert) {
+ circularByteBuffer.clear();
+ convert = false;
+ }
+ inputStream.close();
+ } catch (IOException e) {
+ logger.error("", e);
+ throw new DeactivateException();
+ }
+ }
+
+ protected void work() {
+ if (!convert) {
+ try {
+ synchronized (this) {
+ wait();
+ }
+ } catch (InterruptedException e) {
+ logger.error("", e);
+ }
+ return;
+ }
+ byte[] bytes = new byte[BYTES];
+ int read = 0;
+ try {
+ logger.debug("Writing input to process");
+ while ((read = sourceInputStream.read(bytes)) > 0 && !deactivate) {
+ /* Limit buffer size */
+ while (inputStream.available() > buffer) {
+ int progress = (int) ((1 - (inputStream.available() - buffer) / (float) buffer) * 100);
+ logger.trace("Waiting for buffer to empty: " + progress + "%");
+ sleep(BUFFERING);
+ }
+ processOutputStream.write(bytes, 0, read);
+ }
+ processOutputStream.close();
+ logger.debug("Stopped writing input to process");
+ process.waitFor();
+ logger.debug("Process finished");
+ } catch (IOException e) {
+ } catch (InterruptedException e) {
+ logger.error("", e);
+ }
+ stop();
+ }
+
+ public synchronized InputStream getInputStream() {
+ if (!active()) {
+ if (!activate) {
+ start();
+ }
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ logger.error("", e);
+ }
+ }
+ return inputStream;
+ }
+
+ public synchronized void setInputStream(InputStream inputStream) {
+ this.inputStream = inputStream;
+ }
+
+ class BufferWorker extends Worker {
+ protected void work() {
+ byte[] bytes = new byte[BYTES];
+ int read = 0;
+ try {
+ OutputStream bufferOutputStream = circularByteBuffer.getOutputStream();
+ logger.debug("Start buffering process output");
+ while ((read = processInputStream.read(bytes, 0, BYTES)) > 0) {
+ bufferOutputStream.write(bytes, 0, read);
+ }
+ logger.debug("Finished buffering process output");
+ bufferOutputStream.close();
+ } catch (IOException e) {}
+ stop();
+ }
+ }
+
+ public static void main(String[] args) {
+ Mp3 mp3 = new Mp3(new File("stream.mp3"), 128);
+ InputStream inputStream = mp3.getInputStream();
+
+ /* Play */
+ //Utils.play(inputStream);
+
+ /* Write to file */
+ Utils.write(inputStream, new File("output.mp3"));
+ mp3.exit();
+ }
+}
diff --git a/java/sound/src/main/java/old/List.java b/java/sound/src/main/java/old/List.java
new file mode 100644
index 0000000..c475277
--- /dev/null
+++ b/java/sound/src/main/java/old/List.java
@@ -0,0 +1,198 @@
+package old;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Scanner;
+
+import base.exception.worker.ActivateException;
+import base.worker.Worker;
+
+import com.Ostermiller.util.BufferOverflowException;
+import com.Ostermiller.util.CircularByteBuffer;
+import com.Ostermiller.util.CircularObjectBuffer;
+
+public class List extends Worker {
+ public static final int STEP = 80; // milliseconds
+ public static final int RATE = 192; // kbps
+ public static final int OVERLAP = 20000; // milliseconds
+
+ protected File file;
+ protected String[] fileArray;
+
+ protected int rate;
+ protected int chunk;
+ protected int overlap;
+ protected byte[] bytes;
+ protected boolean next;
+ protected Mp3 mp3, nextMp3;
+
+ protected InputStream mp3InputStream;
+ protected OutputStream audioOutputStream;
+ protected CircularByteBuffer circularByteBuffer;
+ protected CircularObjectBuffer circularStringBuffer;
+
+ public List(File file) {
+ this(file, RATE);
+ }
+
+ public List(File file, int rate) {
+ this.file = file;
+ this.rate = rate;
+ chunk = STEP * rate / 8;
+ overlap = OVERLAP * RATE / 8;
+ bytes = new byte[chunk];
+ next = true;
+ }
+
+ public void exit() {
+ super.exit();
+ if (mp3 != null) {
+ mp3.exit();
+ }
+ if (nextMp3 != null) {
+ nextMp3.exit();
+ }
+ }
+
+ protected synchronized void activate() throws ActivateException {
+ try {
+ Scanner scanner = new Scanner(file);
+ ArrayList fileList = new ArrayList();
+ while (scanner.hasNextLine()) {
+ fileList.add(scanner.nextLine());
+ }
+ if (fileList.size() > 0) {
+ fileArray = fileList.toArray(new String[0]);
+
+ circularByteBuffer = new CircularByteBuffer(CircularByteBuffer.INFINITE_SIZE);
+ audioOutputStream = circularByteBuffer.getOutputStream();
+
+ circularStringBuffer = new CircularObjectBuffer(CircularByteBuffer.INFINITE_SIZE);
+ setNext();
+ super.activate();
+ notifyAll();
+ return;
+ }
+ } catch (FileNotFoundException e) {
+ logger.error("", e);
+ }
+ throw new ActivateException();
+ }
+
+ protected synchronized void work() {
+ try {
+ int left = chunk;
+ while (left > 0) {
+ /* Check for need to load next mp3 */
+ int available = mp3InputStream == null ? -1 : mp3InputStream.available();
+ boolean expect = mp3 == null ? false : mp3.active();
+
+ /* Act when no more data is expected */
+ if (!expect) {
+ if (available < overlap) {
+ setNext();
+ next = false;
+ nextMp3.start();
+ }
+ if (available < 1) {
+ swap();
+ }
+ }
+
+ /* Transfer data */
+ int read = mp3InputStream.read(bytes, 0, left);
+ left -= read;
+ audioOutputStream.write(bytes, 0, read);
+ }
+ } catch (IOException e) {
+ /* Swap to next if stream has stopped */
+ setNext();
+ swap();
+ } catch (IllegalStateException e) {
+ logger.error("", e);
+ }
+ sleep(STEP);
+ }
+
+ protected File getRandomFile() {
+ return new File(fileArray[(int) (Math.random() * fileArray.length)]);
+ }
+
+ public synchronized void setNext() {
+ if (nextMp3 == null) {
+ logger.debug("Initialize next mp3");
+ nextMp3 = new Mp3(getRandomFile(), rate);
+ } else if (next) {
+ logger.debug("Load next mp3");
+ nextMp3.setFile(getRandomFile());
+ }
+ }
+
+ public synchronized void next() {
+ logger.debug("Stop current mp3");
+ mp3.stop();
+ }
+
+ public void swap() {
+ logger.debug("Swap to next mp3");
+ Mp3 swapMp3 = mp3;
+ mp3 = nextMp3;
+ nextMp3 = swapMp3;
+ next = true;
+
+ /* Swap stream and announce title */
+ mp3InputStream = mp3.getInputStream();
+ try {
+ circularStringBuffer.write(mp3.getTitle());
+ } catch (BufferOverflowException e) {
+ logger.error("", e);
+ } catch (IllegalStateException e) {
+ logger.error("", e);
+ } catch (InterruptedException e) {
+ logger.error("", e);
+ }
+ }
+
+ public synchronized InputStream getInputStream() {
+ if (circularByteBuffer == null) {
+ start();
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ logger.error("", e);
+ }
+ }
+ return circularByteBuffer.getInputStream();
+ }
+
+ public synchronized CircularObjectBuffer getMetaBuffer() {
+ if (circularStringBuffer == null) {
+ start();
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ logger.error("", e);
+ }
+ }
+ return circularStringBuffer;
+ }
+
+ public static void main(String[] args) {
+ int rate = 192;
+ List list = new List(new File("mp3"), rate);
+ /*Shoutcast shoutcast = new Shoutcast(null, rate, 9876);
+ shoutcast.start();
+ shoutcast.setInputStream(list.getInputStream());
+ shoutcast.setMetaBuffer(list.getMetaBuffer());*/
+ while (true) {
+ try {
+ Thread.sleep(15000);
+ list.next();
+ } catch (InterruptedException e) {}
+ }
+ }
+}
diff --git a/java/sound/src/main/java/old/Mp3.java b/java/sound/src/main/java/old/Mp3.java
new file mode 100644
index 0000000..589d35e
--- /dev/null
+++ b/java/sound/src/main/java/old/Mp3.java
@@ -0,0 +1,80 @@
+package old;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+import org.farng.mp3.MP3File;
+import org.farng.mp3.TagException;
+
+import sound.util.Utils;
+import base.exception.worker.ActivateException;
+
+public class Mp3 extends Converter {
+ protected File file;
+ protected String title;
+
+ public Mp3(File file) {
+ this(file, -1);
+ }
+
+ public Mp3(File file, int targetRate) {
+ super(null, targetRate);
+ setFile(file);
+ title = "";
+ }
+
+ public synchronized void activate() throws ActivateException {
+ /* Open file */
+ try {
+ sourceInputStream = new FileInputStream(file);
+ } catch (FileNotFoundException e) {
+ logger.error("", e);
+ throw new ActivateException();
+ }
+
+ /* Read ID3V2 tags */
+ try {
+ MP3File mp3File = new MP3File(file);
+ String album = clean(mp3File.getID3v2Tag().getAlbumTitle());
+ String artist = clean(mp3File.getID3v2Tag().getLeadArtist());
+ String track = clean(mp3File.getID3v2Tag().getSongTitle());
+ if (album.isEmpty()) {
+ title = String.format("%s - %s", artist, track, album);
+ } else {
+ title = String.format("%s - %s {%s}", artist, track, album);
+ }
+ logger.debug("Title: " + title);
+ } catch (IOException e) {
+ logger.error("", e);
+ } catch (TagException e) {
+ logger.error("", e);
+ }
+ try {
+ sourceInputStream.skip(100000);
+ } catch (IOException e) {}
+ super.activate();
+ }
+
+ protected String clean(String input) {
+ String output = input.replace("\0", "");
+ return output.replace("ÿþ", "");
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setFile(File file) {
+ this.file = file;
+ }
+
+ public static void main(String[] args) {
+ final Mp3 mp3 = new Mp3(new File("input.mp3"), 128);
+ Utils.write(mp3.getInputStream(), new File("one.mp3"));
+ mp3.setFile(new File("stream.mp3"));
+ Utils.write(mp3.getInputStream(), new File("two.mp3"));
+ mp3.exit();
+ }
+}
diff --git a/java/sound/src/main/java/old/Transducer.java b/java/sound/src/main/java/old/Transducer.java
new file mode 100644
index 0000000..e4ed4a6
--- /dev/null
+++ b/java/sound/src/main/java/old/Transducer.java
@@ -0,0 +1,46 @@
+package old;
+
+import java.io.InputStream;
+
+import sound.Consumer;
+import sound.Producer;
+
+public class Transducer implements Consumer, Producer {
+ public int rate;
+
+ public Transducer(Producer producer) {
+ //setProducer(producer);
+ }
+
+ public int getRate() {
+ return rate;
+ }
+
+ public InputStream getInputStream() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void start(Producer producer) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void start() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void stop() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void exit() {
+ // TODO Auto-generated method stub
+
+ }
+}
diff --git a/java/sound/src/main/java/pipe/Client.java b/java/sound/src/main/java/pipe/Client.java
new file mode 100644
index 0000000..b36d882
--- /dev/null
+++ b/java/sound/src/main/java/pipe/Client.java
@@ -0,0 +1,24 @@
+package pipe;
+
+import java.io.RandomAccessFile;
+
+public class Client {
+ public static void main(String[] args) {
+ try {
+ // Connect to the pipe
+ RandomAccessFile pipe = new RandomAccessFile("\\\\.\\pipe\\detest", "rw");
+ String echoText = "Hello word\n";
+
+ // write to pipe
+ pipe.write(echoText.getBytes());
+
+ // read response
+ String echoResponse = pipe.readLine();
+ System.out.println(echoResponse);
+ pipe.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ }
+}
diff --git a/java/sound/src/main/java/pipe/Pipe.java b/java/sound/src/main/java/pipe/Pipe.java
new file mode 100644
index 0000000..c74b90f
--- /dev/null
+++ b/java/sound/src/main/java/pipe/Pipe.java
@@ -0,0 +1,54 @@
+package pipe;
+
+/**
+ * @author Vikram S Khatri vikram.khatri@us.ibm.com
+ */
+public class Pipe {
+ static final int ERROR_PIPE_CONNECTED = 535;
+ static final int ERROR_BROKEN_PIPE = 109;
+ static final int PIPE_ACCESS_DUPLEX = 0x00000003;
+ static final int PIPE_WAIT = 0x00000000;
+
+ static {
+ System.loadLibrary("pipe");
+ }
+
+ public static final native int CreateNamedPipe(
+ String pipeName,
+ int ppenMode,
+ int pipeMode,
+ int maxInstances,
+ int outBufferSize,
+ int inBufferSize,
+ int defaultTimeOut,
+ int securityAttributes);
+
+ public static final native boolean ConnectNamedPipe(int namedPipeHandle, int overlapped);
+
+ public static final native int GetLastError();
+
+ public static final native boolean CloseHandle(int bbject);
+
+ public static final native byte[] ReadFile(int file, int numberOfBytesToRead);
+
+ public static final native int WriteFile(int file, byte[] buffer, int numberOfBytesToWrite);
+
+ public static final native boolean FlushFileBuffers(int file);
+
+ public static final native boolean DisconnectNamedPipe(int namedPipeHandle);
+
+ public static final native int CreateFile(
+ String fileName,
+ int desiredAccess,
+ int shareMode,
+ int securityAttributes,
+ int creationDisposition,
+ int flagsAndAttributes,
+ int templateFile);
+
+ public static final native boolean WaitNamedPipe(String namedPipeName, int timeOut);
+
+ public static final native String FormatMessage(int errorCode);
+
+ public static final native void Print(String message);
+}
diff --git a/java/sound/src/main/java/pipe/TestPipe.java b/java/sound/src/main/java/pipe/TestPipe.java
new file mode 100644
index 0000000..b1e1e32
--- /dev/null
+++ b/java/sound/src/main/java/pipe/TestPipe.java
@@ -0,0 +1,87 @@
+package pipe;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+
+public class TestPipe {
+
+ private int namedPipeHandle;
+ private String pipeName, srcFile;
+ private int pipeBuffer = 131072, fileBuffer = 8192;
+
+ public TestPipe(String pipeName, String srcFile) {
+ this.pipeName = pipeName;
+ this.srcFile = srcFile;
+ }
+
+ private void log(String message) {
+ System.out.println(message);
+ }
+
+ private boolean createPipe() {
+ namedPipeHandle = Pipe.CreateNamedPipe(
+ pipeName,
+ Pipe.PIPE_ACCESS_DUPLEX,
+ Pipe.PIPE_WAIT,
+ 5,
+ pipeBuffer,
+ pipeBuffer,
+ 0xffffffff,
+ 0);
+ if (namedPipeHandle == -1) {
+ log("CreateNamedPipe failed for " + pipeName + " for error Message " + Pipe.FormatMessage(Pipe.GetLastError()));
+ } else {
+ log("Named Pipe " + pipeName + " created successfully Handle=" + namedPipeHandle);
+ }
+ return namedPipeHandle != -1;
+ }
+
+ private boolean connectToPipe() {
+ log("Waiting for a client to connect to pipe " + pipeName);
+ boolean connected = Pipe.ConnectNamedPipe(namedPipeHandle, 0);
+ if (!connected) {
+ int lastError = Pipe.GetLastError();
+ if (lastError == Pipe.ERROR_PIPE_CONNECTED)
+ connected = true;
+ }
+ log((connected ? "Connected to the pipe " : "Falied to connect to the pipe ") + pipeName);
+ return connected;
+ }
+
+ public void runPipe() {
+ if (createPipe() && connectToPipe()) {
+ log("Client connected.");
+ try {
+ File f1 = new File(this.srcFile);
+ InputStream in = new FileInputStream(f1);
+ log("Sending data to the pipe");
+ byte[] buf = new byte[fileBuffer];
+ int len, bytesWritten;
+ while ((len = in.read(buf)) > 0) {
+ bytesWritten = Pipe.WriteFile(namedPipeHandle, buf, len);
+ log("Sent " + len + "/" + bytesWritten + " bytes to the pipe");
+ if (bytesWritten == -1) {
+ int errorNumber = Pipe.GetLastError();
+ log("Error Writing to pipe " + Pipe.FormatMessage(errorNumber));
+ }
+ }
+ in.close();
+ Pipe.FlushFileBuffers(namedPipeHandle);
+ Pipe.CloseHandle(namedPipeHandle);
+ Pipe.DisconnectNamedPipe(namedPipeHandle);
+ log("Writing to the pipe completed.");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public static void main(String[] args) {
+ String pipeName = "\\\\.\\pipe\\detest";
+ String fileName = "txt/bla.txt";
+ //fileName = "C:\\Users\\Rik\\Music\\Artists\\+44\\When Your Heart Stops Beating\\+44 - 155.mp3";
+ TestPipe testPipe = new TestPipe(pipeName, fileName);
+ testPipe.runPipe();
+ }
+}
diff --git a/java/sound/src/main/java/sound/Consumer.java b/java/sound/src/main/java/sound/Consumer.java
new file mode 100644
index 0000000..9174078
--- /dev/null
+++ b/java/sound/src/main/java/sound/Consumer.java
@@ -0,0 +1,7 @@
+package sound;
+
+public interface Consumer {
+ public void start(Producer producer);
+ public void stop();
+ public void exit();
+}
diff --git a/java/sound/src/main/java/sound/Format.java b/java/sound/src/main/java/sound/Format.java
new file mode 100644
index 0000000..c24c3d3
--- /dev/null
+++ b/java/sound/src/main/java/sound/Format.java
@@ -0,0 +1,13 @@
+package sound;
+
+import javax.sound.sampled.AudioFormat;
+
+public interface Format extends Cloneable {
+ public interface Standard extends Format {
+ public AudioFormat getAudioFormat();
+ }
+
+ public interface Mp3 extends Format {
+ public int getRate();
+ }
+}
\ No newline at end of file
diff --git a/java/sound/src/main/java/sound/Producer.java b/java/sound/src/main/java/sound/Producer.java
new file mode 100644
index 0000000..c25eb48
--- /dev/null
+++ b/java/sound/src/main/java/sound/Producer.java
@@ -0,0 +1,10 @@
+package sound;
+
+import java.io.InputStream;
+
+public interface Producer extends Format {
+ public InputStream getInputStream();
+ public void start();
+ public void stop();
+ public void exit();
+}
\ No newline at end of file
diff --git a/java/sound/src/main/java/sound/Source.java b/java/sound/src/main/java/sound/Source.java
new file mode 100644
index 0000000..8fcf427
--- /dev/null
+++ b/java/sound/src/main/java/sound/Source.java
@@ -0,0 +1,161 @@
+package sound;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.LineUnavailableException;
+import javax.sound.sampled.SourceDataLine;
+
+import javazoom.jl.decoder.JavaLayerException;
+import javazoom.jl.player.Player;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import sound.util.Tool;
+import base.exception.worker.ActivateException;
+import base.exception.worker.DeactivateException;
+import base.worker.Worker;
+
+public class Source implements Consumer {
+ protected Logger logger = LoggerFactory.getLogger(getClass());
+
+ protected static final int BUFFER_SIZE = 1024 * 4; // in bytes
+ protected static final int FRAMES = 10; // count
+
+ protected String name;
+ protected Producer producer;
+ protected InputStream producerInputStream;
+ protected Worker worker;
+
+ public Source(String name) throws LineUnavailableException {
+ this.name = name;
+ }
+
+ public void start() {
+ if (worker != null) {
+ worker.start(true);
+ }
+ }
+
+ public void start(Producer producer) {
+ this.producer = producer;
+ producerInputStream = producer.getInputStream();
+ if (worker != null) {
+ worker.exit();
+ }
+ if (producer instanceof Format.Standard) {
+ logger.debug("Format.Standard");
+ worker = new DefaultWorker((Format.Standard) producer);
+ } else if (producer instanceof Format.Mp3) {
+ logger.debug("Format.Mp3");
+ worker = new Mp3Worker((Format.Mp3) producer);
+ }
+ start();
+ }
+
+ public void stop() {
+ if (worker != null) {
+ worker.stop();
+ }
+ }
+
+ public void exit() {
+ if (worker != null) {
+ worker.exit();
+ }
+ }
+
+ protected class DefaultWorker extends Worker {
+ protected Format.Standard format;
+ protected SourceDataLine line;
+
+ public DefaultWorker(Format.Standard format) {
+ this.format = format;
+ }
+
+ public void activate() throws ActivateException {
+ AudioFormat audioFormat = format.getAudioFormat();
+ try {
+ if (line == null) {
+ line = Tool.getSourceDataLine(name, audioFormat);
+ }
+ if (!line.isOpen()) {
+ line.open();
+ }
+ } catch (LineUnavailableException e) {
+ logger.error("", e);
+ throw new ActivateException();
+ }
+ if (!line.isRunning()) {
+ line.start();
+ }
+ super.activate();
+ }
+
+ public void deactivate() throws DeactivateException {
+ super.deactivate();
+ line.flush();
+ }
+
+ public void exit() {
+ super.exit();
+ line.close();
+ }
+
+ protected void work() {
+ try {
+ byte[] buffer = new byte[BUFFER_SIZE];
+ int read = producerInputStream.read(buffer, 0, buffer.length);
+ if (read > 0) {
+ line.write(buffer, 0, read);
+ } else {
+ exit();
+ }
+ } catch (IOException e) {
+ logger.error("", e);
+ exit();
+ }
+ }
+ }
+
+ protected class Mp3Worker extends Worker {
+ protected Format.Mp3 format;
+ protected Player player;
+
+ public Mp3Worker(Format.Mp3 format) {
+ this.format = format;
+ }
+
+ public void activate() throws ActivateException {
+ producer.start();
+ super.activate();
+ }
+
+ public void deactivate() throws DeactivateException {
+ super.deactivate();
+ producer.stop();
+ }
+
+ public void exit() {
+ super.exit();
+ player.close();
+ }
+
+ protected void work() {
+ try {
+ if (player == null) {
+ player = new Player(producerInputStream);
+ sleep(SLEEP);
+ }
+ player.play(FRAMES);
+ } catch (JavaLayerException e) {
+ logger.error("", e);
+ }
+ if (player.isComplete()) {
+ stop();
+ }
+ }
+ }
+}
diff --git a/java/sound/src/main/java/sound/consumer/Port.java b/java/sound/src/main/java/sound/consumer/Port.java
new file mode 100644
index 0000000..c39446a
--- /dev/null
+++ b/java/sound/src/main/java/sound/consumer/Port.java
@@ -0,0 +1,121 @@
+package sound.consumer;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import javax.sound.sampled.AudioFormat;
+
+import sound.Consumer;
+import sound.Format;
+import sound.Format.Standard;
+import sound.Producer;
+import sound.util.SoxBuilder;
+import sound.util.SoxBuilder.File;
+import sound.util.SoxBuilder.File.Type;
+import sound.util.SoxBuilder.Option;
+import base.exception.worker.ActivateException;
+import base.exception.worker.DeactivateException;
+import base.worker.Worker;
+
+public class Port extends Worker implements Consumer {
+ protected static final int BUFFER_SIZE = 1024 * 4; // in bytes
+
+ protected String device;
+ protected Producer producer;
+ protected Process process;
+ protected InputStream producerInputStream;
+ protected OutputStream processOutputStream;
+ protected ProcessBuilder processBuilder;
+
+ public Port() {
+ this("0");
+ }
+
+ public Port(String device) {
+ this.device = device;
+ }
+
+ public void start(Producer producer) {
+ start(producer, THREAD);
+ }
+
+ @SuppressWarnings("static-access")
+ public void start(Producer producer, boolean thread) {
+ this.producer = producer;
+ producerInputStream = producer.getInputStream();
+
+ String command = "";
+ if (producer instanceof Standard) {
+ AudioFormat audioFormat = ((Standard) producer).getAudioFormat();
+ SoxBuilder.addFile(File.setType(Type.STANDARD).setOptions(audioFormat));
+ } else if (producer instanceof Format.Mp3) {
+ SoxBuilder.addFile(File.setType(Type.STANDARD).setOption(File.Format.MP3));
+ }
+ command = SoxBuilder
+ .setOption(Option.QUIET)
+ .addFile(File.setType(Type.DEVICE))
+ .build();
+
+ logger.debug(String.format("Build process (\"%s\")", command));
+ processBuilder = new ProcessBuilder(command.split(" "));
+ processBuilder.environment().put("AUDIODEV", device);
+
+ start(thread);
+ }
+
+ protected void activate() throws ActivateException {
+ producer.start();
+ if (process == null) {
+ try {
+ process = processBuilder.start();
+ } catch (IOException e) {
+ logger.error("", e);
+ throw new ActivateException();
+ }
+ processOutputStream = process.getOutputStream();
+ }
+ super.activate();
+ }
+
+ protected void deactivate() throws DeactivateException {
+ super.deactivate();
+ try {
+ processOutputStream.flush();
+ } catch (IOException e) {
+ logger.error("", e);
+ throw new DeactivateException();
+ }
+ }
+
+ public void exit() {
+ try {
+ logger.debug("close process output stream");
+ processOutputStream.close();
+
+ logger.debug("wait for process to terminate");
+ process.waitFor();
+ } catch (IOException e) {
+ logger.error("", e);
+ } catch (InterruptedException e) {
+ logger.error("", e);
+ } finally {
+ process = null;
+ }
+ }
+
+ protected void work() {
+ try {
+ byte[] buffer = new byte[BUFFER_SIZE];
+ int read = producerInputStream.read(buffer, 0, buffer.length);
+ if (read > 0) {
+ processOutputStream.write(buffer, 0, read);
+ } else {
+ exit();
+ }
+ } catch (IOException e) {
+ logger.error("", e);
+ exit();
+ }
+ }
+}
diff --git a/java/sound/src/main/java/sound/producer/Stream.java b/java/sound/src/main/java/sound/producer/Stream.java
new file mode 100644
index 0000000..24500a8
--- /dev/null
+++ b/java/sound/src/main/java/sound/producer/Stream.java
@@ -0,0 +1,199 @@
+package sound.producer;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.net.Socket;
+import java.net.URL;
+
+import sound.Format;
+import sound.Producer;
+import sound.stream.HoardedInputStream;
+import base.exception.worker.ActivateException;
+import base.exception.worker.DeactivateException;
+import base.worker.Worker;
+
+import com.Ostermiller.util.CircularByteBuffer;
+import com.Ostermiller.util.CircularObjectBuffer;
+
+public class Stream extends Worker implements Producer, Format.Mp3 {
+ public static final int STEP = 80; // in milliseconds
+
+ protected String http;
+ protected Socket socket;
+ protected InputStream socketInputStream;
+ protected OutputStreamWriter socketOutputStreamWriter;
+ protected HoardedInputStream hoardedInputStream;
+ protected int meta;
+ protected int rate;
+ protected int chunk;
+ protected int untilMeta;
+ protected CircularByteBuffer audioCircularByteBuffer;
+ protected CircularObjectBuffer metaCircularObjectBuffer;
+ protected String metaData;
+
+ public Stream(String http) {
+ this.http = http;
+ meta = -1;
+ rate = -1;
+ audioCircularByteBuffer = new CircularByteBuffer(CircularByteBuffer.INFINITE_SIZE);
+ metaCircularObjectBuffer = new CircularObjectBuffer();
+ }
+
+ protected void connect(URL url) {
+ try {
+ /* Open socket communication */
+ socket = new Socket(url.getHost(), url.getPort());
+ socketInputStream = socket.getInputStream();
+ socketOutputStreamWriter = new OutputStreamWriter(socket.getOutputStream());
+
+ /* Write stream request */
+ if (url.getFile().equals("")) {
+ socketOutputStreamWriter.write("GET / HTTP/1.1\r\n");
+ } else {
+ socketOutputStreamWriter.write("GET " + url.getFile() + " HTTP/1.1\r\n");
+ }
+ socketOutputStreamWriter.write("Host: " + url.getHost() + "\r\n");
+ //socketOutputStreamWriter.write("Icy-MetaData: 1\r\n");
+ socketOutputStreamWriter.write("Connection: close\r\n");
+ socketOutputStreamWriter.write("\r\n");
+ socketOutputStreamWriter.flush();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ protected void activate() throws ActivateException {
+ try {
+ /* Initialize connection */
+ URL url = new URL(http);
+
+ /* Parse headers */
+ connect(url);
+ InputStreamReader inputStreamReader = new InputStreamReader(socketInputStream);
+ StringBuffer stringBuffer = new StringBuffer();
+ char character;
+ int skip = 0;
+ while ((character = (char) inputStreamReader.read()) > 0) {
+ ++skip;
+ if (character == '\n') {
+ /* Fetch relevant headers */
+ String line = stringBuffer.toString().trim();
+ if (line.startsWith("icy-metaint")) {
+ meta = Integer.valueOf(line.substring(line.indexOf(":") + 1).trim());
+ } else if (line.startsWith("icy-br")) {
+ rate = Integer.valueOf(line.substring(line.indexOf(":") + 1).trim());
+ } else if (line.equals("")) {
+ break;
+ }
+ stringBuffer = new StringBuffer();
+ } else {
+ stringBuffer.append(character);
+ }
+ }
+ inputStreamReader.close();
+
+ /* Reconnect to bypass pre-buffering problems */
+ connect(url);
+ socketInputStream = socket.getInputStream();
+ socketInputStream.skip(skip);
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (NumberFormatException e) {
+ e.printStackTrace();
+ }
+
+ /* Calculate streaming parameters */
+ //untilMeta = meta;
+ chunk = STEP * rate / 8;
+ super.activate();
+ }
+
+ public void deactivate() throws DeactivateException {
+ super.deactivate();
+ audioCircularByteBuffer.clear();
+ metaCircularObjectBuffer.clear();
+ try {
+ hoardedInputStream.clear();
+ } catch (IOException e) {
+ logger.error("", e);
+ throw new DeactivateException();
+ }
+ }
+
+ protected void work() {
+ int left = chunk;
+
+ /* Handle media at appropriate times *
+ while (meta > 0 && left >= untilMeta) {
+ stream(untilMeta);
+ left -= untilMeta;
+ meta();
+ untilMeta = meta;
+ }*/
+
+ /* Stream at fixed rate */
+ stream(left);
+ //untilMeta -= left;
+ sleep(STEP);
+ }
+
+ protected void stream(int length) {
+ try {
+ byte[] bytes = new byte[length];
+ int read = 0;
+ while (length > 0 && (read = socketInputStream.read(bytes)) > 0) {
+ length -= read;
+ audioCircularByteBuffer.getOutputStream().write(bytes);
+ }
+ } catch (IOException e) {
+ logger.error(e.getMessage());
+ stop();
+ }
+ }
+
+ protected void meta() {
+ try {
+ /* Retrieve data length */
+ byte[] data = new byte[1];
+ socketInputStream.read(data);
+
+ int length = 16 * data[0];
+ data = new byte[length];
+ socketInputStream.read(data);
+
+ /* Check for new data */
+ String newMetaData = new String(data);
+ if (!newMetaData.isEmpty() && !newMetaData.equals(metaData)) {
+ metaData = newMetaData;
+ metaCircularObjectBuffer.write(new String(data));
+ logger.debug("data: " + metaData);
+ }
+ return;
+ } catch (IOException e) {
+ logger.error("", e);
+ } catch (IllegalStateException e) {
+ logger.error("", e);
+ } catch (InterruptedException e) {
+ logger.error("", e);
+ }
+ stop();
+ return;
+ }
+
+ public InputStream getInputStream() {
+ if (hoardedInputStream == null) {
+ hoardedInputStream = new HoardedInputStream(audioCircularByteBuffer.getInputStream());
+ }
+ return hoardedInputStream;
+ }
+
+ public CircularObjectBuffer getMetaBufferStream() {
+ return metaCircularObjectBuffer;
+ }
+
+ public int getRate() {
+ return rate;
+ }
+}
diff --git a/java/sound/src/main/java/sound/producer/Target.java b/java/sound/src/main/java/sound/producer/Target.java
new file mode 100644
index 0000000..e752e5d
--- /dev/null
+++ b/java/sound/src/main/java/sound/producer/Target.java
@@ -0,0 +1,97 @@
+package sound.producer;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.LineUnavailableException;
+import javax.sound.sampled.TargetDataLine;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import sound.Format;
+import sound.Producer;
+import sound.stream.HoardedInputStream;
+import sound.util.Tool;
+
+public class Target implements Producer, Format.Standard {
+ protected Logger logger = LoggerFactory.getLogger(getClass());
+
+ protected Standard format;
+
+ protected TargetDataLine line;
+ protected InputStream targetInputStream;
+ protected HoardedInputStream hoardedInputStream;
+
+ protected AudioFormat audioFormat;
+
+ public Target(String name) throws LineUnavailableException {
+ logger.debug(String.format("Target \"%s\" without format", name));
+ line = Tool.getTargetDataLine(name);
+ audioFormat = line.getFormat();
+ targetInputStream = new TargetInputStream();
+ }
+
+ public Target(String name, AudioFormat audioFormat) throws LineUnavailableException {
+ logger.debug(String.format("Target \"%s\" with format: %s", name, audioFormat));
+ this.audioFormat = audioFormat;
+ line = Tool.getTargetDataLine(name, audioFormat);
+ targetInputStream = new TargetInputStream();
+ }
+
+ public AudioFormat getAudioFormat() {
+ return audioFormat;
+ }
+
+ public InputStream getInputStream() {
+ return targetInputStream;
+ }
+
+ public class TargetInputStream extends InputStream {
+ protected boolean open;
+
+ public TargetInputStream() {
+ open = false;
+ }
+
+ public int read() throws IOException {
+ start();
+ byte[] buffer = new byte[1];
+ line.read(buffer, 0, 1);
+ return (int) buffer[0];
+ }
+
+ public int read(byte[] buffer, int offset, int length) {
+ start();
+ line.read(buffer, offset, length);
+ return length;
+ }
+
+ public int available() {
+ start();
+ return line.available();
+ }
+ }
+
+ public void start() {
+ if (!line.isOpen()) {
+ try {
+ line.open();
+ } catch (LineUnavailableException e) {
+ logger.error("", e);
+ }
+ }
+ if (!line.isRunning()) {
+ line.start();
+ }
+ }
+
+ public void stop() {
+ line.flush();
+ }
+
+ public void exit() {
+ line.close();
+ }
+}
diff --git a/java/sound/src/main/java/sound/stream/HoardedInputStream.java b/java/sound/src/main/java/sound/stream/HoardedInputStream.java
new file mode 100644
index 0000000..beb941c
--- /dev/null
+++ b/java/sound/src/main/java/sound/stream/HoardedInputStream.java
@@ -0,0 +1,76 @@
+package sound.stream;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class HoardedInputStream extends BufferedInputStream {
+ protected Logger logger = LoggerFactory.getLogger(getClass());
+
+ protected static final int SLEEP = 500; // in milliseconds
+ protected static final int BUFFER_SIZE = 30000; // in bytes
+ protected static final int MINIMUM_SIZE = 1000; // in bytes
+
+ protected int bufferSize;
+ protected int minimumSize;
+ protected boolean hoard;
+
+ public HoardedInputStream(InputStream inputStream) {
+ this(inputStream, BUFFER_SIZE, MINIMUM_SIZE);
+ }
+
+ public HoardedInputStream(InputStream inputStream, int bufferSize) {
+ super(inputStream, bufferSize);
+ this.bufferSize = bufferSize;
+ hoard = true;
+ }
+
+ public HoardedInputStream(InputStream inputStream, int bufferSize, int minimumSize) {
+ this(inputStream, bufferSize);
+ this.minimumSize = minimumSize;
+ }
+
+ public int read() throws IOException {
+ hoard();
+ byte[] buffer = new byte[1];
+ in.read(buffer, 0, 1);
+ return (int) buffer[0];
+ }
+
+ public int read(byte[] buffer, int offset, int length) throws IOException {
+ hoard();
+ in.read(buffer, offset, length);
+ return length;
+ }
+
+ public void hoard() throws IOException {
+ int available = available();
+ if (hoard && available < MINIMUM_SIZE) {
+ long time = System.currentTimeMillis();
+ do {
+ try {
+ Thread.sleep(SLEEP);
+ } catch (InterruptedException e) {
+ logger.warn("", e);
+ }
+ } while (available() < BUFFER_SIZE);
+ logger.debug(String.format("Buffered %d bytes in %s milliseconds", BUFFER_SIZE - available, System.currentTimeMillis() - time));
+ }
+ }
+
+ public void clear() throws IOException {
+ this.buf = new byte[buf.length];
+ reset();
+ }
+
+ public void drain() {
+ drain(true);
+ }
+
+ public void drain(boolean drain) {
+ hoard = !drain;
+ }
+}
diff --git a/java/sound/src/main/java/sound/util/SoxBuilder.java b/java/sound/src/main/java/sound/util/SoxBuilder.java
new file mode 100644
index 0000000..9870d50
--- /dev/null
+++ b/java/sound/src/main/java/sound/util/SoxBuilder.java
@@ -0,0 +1,321 @@
+package sound.util;
+
+import java.util.HashMap;
+import java.util.Map.Entry;
+
+import javax.sound.sampled.AudioFormat;
+
+import sound.util.SoxBuilder.Option.Combine;
+import sound.util.SoxBuilder.Option.Replay;
+
+public final class SoxBuilder {
+ protected static SoxBuilder instance;
+ protected static HashMap optionMap;
+ protected static String files;
+ protected static String effects;
+
+ static {
+ instance = new SoxBuilder();
+ reset();
+ }
+
+ public static void reset() {
+ optionMap = new HashMap();
+ files = "";
+ effects = "";
+ }
+
+ public static SoxBuilder setOption(Option option, String value) {
+ optionMap.put(option.getCode(), value);
+ return instance;
+ }
+
+ public static SoxBuilder setOption(Option option) {
+ return SoxBuilder.setOption(option, "");
+ }
+
+ public static SoxBuilder setOption(Option option, int value) {
+ return SoxBuilder.setOption(option, String.valueOf(value));
+ }
+
+ public static SoxBuilder setOption(Option option, Combine combine) {
+ return SoxBuilder.setOption(option, combine.getCode());
+ }
+
+ public static SoxBuilder setOption(Combine combine) {
+ return SoxBuilder.setOption(Option.COMBINE, combine);
+ }
+
+ public static SoxBuilder setOption(Option option, Replay replay) {
+ return SoxBuilder.setOption(option, replay.toString().toLowerCase());
+ }
+
+ public static SoxBuilder setOption(Replay replay) {
+ return SoxBuilder.setOption(Option.REPLAY, replay);
+ }
+
+ public static SoxBuilder addFile(File file) {
+ files = String.format("%s %s", files, file.build());
+ return instance;
+ }
+
+ public static SoxBuilder addEffect(Effect effect) {
+ effects = String.format("%s %s", effects, effect.build());
+ return instance;
+ }
+
+ public String build() {
+ String build = "sox";
+ for (Entry entry : optionMap.entrySet()) {
+ String value = entry.getValue();
+ if (value.equals("")) {
+ build = String.format("%s %s", build, entry.getKey());
+ } else {
+ String option = String.format("%s %s", entry.getKey(), value);
+ build = String.format("%s %s", build, option);
+ }
+ }
+ build = String.format("%s%s%s", build, files, effects);
+ reset();
+ return build;
+ }
+
+ public enum Environment {
+ AUDIODRIVER, AUDIODEV
+ }
+
+ public enum Option {
+ BUFFER ("--buffer"), // default=8192
+ INPUT_BUFFER ("--input-buffer"),
+ CLOBBER ("--clobber"),
+ COMBINE ("--combine"), // |Combine|
+ NO_DITHER ("--no-dither"), // (-D)
+ EFFECTS_FILE ("--efects-file"),
+ GUARD ("--guard"), // (-G)
+ MIX ("-m"), // (--combine mix)
+ MERGE ("-M"), // (--combine merge)
+ MAGIC ("--magic"),
+ MULTI_THREADED ("--multi-threaded"),
+ SINGLE_THREADED ("--single-threaded"),
+ NORM ("--norm"), // [=dB-level]
+ PLAY_RATE_ARG ("--play-rate-arg"),
+ QUIET ("--no-show-progress"), // (-q)
+ REPEATABLE ("-R"),
+ REPLAY ("--replay-gain"), // |Replay|
+ MULTIPLY ("-T"), // (--combine multiply)
+ TEMP ("--temp");
+
+ protected String code;
+
+ private Option(String code) {
+ this.code = code;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public enum Combine {
+ CONCATENATE ("concatenate"),
+ MERGE ("merge"), // (-M)
+ MIX ("mix"), // (-m)
+ MIX_POWER ("mix-power"),
+ MULTIPLY ("multiply"), // (-T)
+ SEQUENCE ("sequence");
+
+ protected String code;
+
+ private Combine(String code) {
+ this.code = code;
+ }
+
+ public String getCode() {
+ return code;
+ }
+ }
+
+ public enum Replay {
+ TRACK, ALBUM, OFF
+ }
+ }
+
+ public static class File {
+ protected static File instance;
+
+ protected static HashMap optionMap;
+ protected static Type type;
+
+ static {
+ instance = new File();
+ reset();
+ }
+
+ public static void reset() {
+ optionMap = new HashMap();
+ type = Type.PIPE;
+ }
+
+ public static File setOption(Option option, String value) {
+ optionMap.put(option.getCode(), value);
+ return instance;
+ }
+
+ public static File setOption(Option option) {
+ return File.setOption(option, "");
+ }
+
+ public static File setOption(Option option, int value) {
+ return File.setOption(option, String.valueOf(value));
+ }
+
+ public static File setOption(Option option, Encoding encoding) {
+ return File.setOption(option, encoding.getCode());
+ }
+
+ public static File setOption(Encoding encoding) {
+ return File.setOption(Option.ENCODING, encoding);
+ }
+
+ public static File setOption(Option option, Format format) {
+ return File.setOption(option, format.toString().toLowerCase());
+ }
+
+ public static File setOption( Format format) {
+ return File.setOption(Option.FORMAT, format);
+ }
+
+ public static File setOption(Option option, Endian endian) {
+ return File.setOption(option, endian.toString().toLowerCase());
+ }
+
+ public static File setOption(Endian endian) {
+ return File.setOption(Option.ENDIAN, endian);
+ }
+
+ public File setOptions(AudioFormat audioFormat) {
+ setOption(Option.CHANNELS, audioFormat.getChannels());
+ setOption(Option.RATE, String.format("%sk", String.valueOf(audioFormat.getSampleRate() / 1000f)));
+ AudioFormat.Encoding encoding = audioFormat.getEncoding();
+ int bits = audioFormat.getSampleSizeInBits();
+ if (encoding.equals(AudioFormat.Encoding.ALAW)) {
+ setOption(Format.AL);
+ setOption(Encoding.A_LAW);
+ } else if (encoding.equals(AudioFormat.Encoding.ULAW)) {
+ setOption(Format.UL);
+ setOption(Encoding.U_LAW);
+ } else if (encoding.equals(AudioFormat.Encoding.PCM_SIGNED)) {
+ setOption(Format.valueOf(String.format("S%d", bits)));
+ setOption(Encoding.SIGNED_INTEGER);
+ } else if (encoding.equals(AudioFormat.Encoding.PCM_UNSIGNED)) {
+ setOption(Format.valueOf(String.format("U%d", bits)));
+ setOption(Encoding.UNSIGNED_INTEGER);
+ }
+ setOption(audioFormat.isBigEndian() ? Endian.BIG : Endian.LITTLE);
+ return instance;
+ }
+
+ public static File setType(Type type) {
+ File.type = type;
+ return instance;
+ }
+
+ public String build() {
+ String build = type.getCode();
+ for (Entry entry : optionMap.entrySet()) {
+ String value = entry.getValue();
+ if (value.equals("")) {
+ build = String.format("%s %s", entry.getKey(), build);
+ } else {
+ String option = String.format("%s %s", entry.getKey(), value);
+ build = String.format("%s %s", option, build);
+ }
+ }
+ reset();
+ return build;
+ }
+
+ public enum Option {
+ BITS ("--bits"), // (-b)
+ CHANNELS ("--channels"), // (-c)
+ ENCODING ("--encoding"), // (-e), |Encoding|
+ NO_GLOB ("--no-glob"),
+ RATE ("--rate"), // (-r)
+ FORMAT ("--type"), // (-t), |Format|
+ ENDIAN ("--endian"), // (-L, -B, -x), |Endian|
+ REVERSE_NIBBLES ("--reverse-nibbles"), // (-N)
+ REVERSE_BITS ("--reverse-bits"), // (-X)
+ /* Input only */
+ IGNORE_LENGTH ("--ignore-length"),
+ VOLUME ("--volume"), // (-v)
+ /* Output only */
+ ADD_COMMENT ("--add-comment"),
+ COMMENT ("--comment"),
+ COMMENT_FILE ("--comment-file"),
+ COMPRESSION ("--compression"); // -C
+
+ protected String code;
+
+ private Option(String code) {
+ this.code = code;
+ }
+
+ public String getCode() {
+ return code;
+ }
+ }
+
+ public enum Encoding {
+ SIGNED_INTEGER ("signed-integer"), // PCM data stored as signed integers
+ UNSIGNED_INTEGER ("unsigned-integer"), // PCM data stored as unsigned integers
+ FLOATING_POINT ("floating-point"), // PCM data stored as single precision (32-bit) or double precision (64-bit) floating-point numbers
+ A_LAW ("a-lawW"), // International telephony standard for logarithmic encoding to 8 bits per sample (~13-bit PCM)
+ U_LAW ("u-law"), // North American telephony standard for logarithmic encoding to 8 bits per sample (~14-bit PCM)
+ MU_LAW ("mu-law"), // alias for u-law (~14-bit PCM)
+ OKI_ADPCM ("oki-adpcm"), // OKI (VOX, Dialogic or Intel) 4-bit ADPCM (~12-bit PCM)
+ IMA_ADPCM ("ima-adpcm"), // IMA (DVI) 4-bit ADPCM (~13-bit PCM)
+ MS_ADPCM ("ms-adpcm"), // Microsoft 4-bit ADPCM (~14-bit PCM)
+ GSM_FULL_RATE ("gsm-full-rate"); // Several audio formats used for digital wireless telephone calls
+
+ protected String code;
+
+ private Encoding(String code) {
+ this.code = code;
+ }
+
+ public String getCode() {
+ return code;
+ }
+ }
+
+ public enum Format {
+ AIF, AIFC, AIFF, AIFFC, AL, AMB, AMR, ANY, ARL, AU, AVR, BIN, CAF, CDDA, CDR, CVS, CVSD, CVU, DAT, DVMS, EDU, F32, F64, FAP, FLAC, FSSD, GSM, GSRT, HCOM, HTK, IMA, IRCAM, LA, LPC, LPC10, LU, M3U, M4A, MAT, MAT4, MAT5, MAUD, MP2, MP3, MP4, NIST, OGG, PAF, PLS, PRC, PVF, RAW, S16, S24, S32, S8, SD2, SDS, SF, SLN, SMP, SND, SNDR, SNDT, SOU, SOX, SPH, TXW, U16, U24, U32, U8, UL, VMS, VOC, VORBIS, VOX, W64, WAV, WAVPCM, WV, WVE, XA, XI;
+ }
+
+ public enum Endian {
+ LITTLE, BIG, SWAP;
+ }
+
+ public enum Type {
+ STANDARD ("-"), // -t must be given
+ PIPE ("-p"), // (--sox-pipe)
+ DEVICE ("-d"), // (--default-device)
+ NULL ("-n"); // (--null)
+
+ protected String code;
+
+ private Type(String code) {
+ this.code = code;
+ }
+
+ public String getCode() {
+ return code;
+ }
+ }
+ }
+
+ public class Effect {
+ public String build() {
+ return null;
+ }
+ }
+}
diff --git a/java/sound/src/main/java/sound/util/Tool.java b/java/sound/src/main/java/sound/util/Tool.java
new file mode 100644
index 0000000..22d5076
--- /dev/null
+++ b/java/sound/src/main/java/sound/util/Tool.java
@@ -0,0 +1,140 @@
+package sound.util;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.DataLine;
+import javax.sound.sampled.Line;
+import javax.sound.sampled.LineUnavailableException;
+import javax.sound.sampled.Mixer;
+import javax.sound.sampled.Port;
+import javax.sound.sampled.Port.Info;
+import javax.sound.sampled.SourceDataLine;
+import javax.sound.sampled.TargetDataLine;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Tool {
+ protected static Logger logger = LoggerFactory.getLogger(Tool.class);
+
+ protected static HashMap> targetMap;
+ protected static HashMap> sourceMap;
+ protected static ArrayList portList;
+
+ protected static ArrayList targetList;
+ protected static ArrayList sourceList;
+
+ static {
+ Tool tool = new Tool();
+
+ targetMap = new HashMap>();
+ sourceMap = new HashMap>();
+ targetList = new ArrayList();
+ sourceList = new ArrayList();
+ portList = new ArrayList();
+
+ for (Mixer.Info mixerInfo : AudioSystem.getMixerInfo()) {
+ String name = mixerInfo.getName();
+ Mixer mixer = AudioSystem.getMixer(mixerInfo);
+
+ for (Line.Info lineInfo : mixer.getSourceLineInfo()) {
+ String lineClassName = lineInfo.getLineClass().getName();
+ if (lineClassName.equals("javax.sound.sampled.SourceDataLine")) {
+ if (mixer.isLineSupported(lineInfo)) {
+ logger.debug(" " + name);
+ sourceMap.put(name, tool.new Device(mixer, lineInfo));
+ }
+ }
+ }
+ for (Line.Info lineInfo : mixer.getTargetLineInfo()) {
+ String lineClassName = lineInfo.getLineClass().getName();
+ if (lineClassName.equals("javax.sound.sampled.TargetDataLine")) {
+ if (mixer.isLineSupported(lineInfo)) {
+ logger.debug(" " + name);
+ targetMap.put(name, tool.new Device(mixer, lineInfo));
+ }
+ } else if (lineClassName.equals("javax.sound.sampled.Port")) {
+ name = name.substring(5);
+ try {
+ Port port = (Port) mixer.getLine(lineInfo);
+ Port.Info portInfo = (Info) port.getLineInfo();
+ if (!targetMap.containsKey(name) || portInfo.equals(Port.Info.LINE_OUT) || portInfo.equals(Port.Info.SPEAKER)) {
+ logger.debug(" " + name);
+ portList.add(name);
+ }
+ } catch (LineUnavailableException e) {
+ logger.error("", e);
+ }
+ }
+ }
+ }
+ }
+
+ public static String[] getTargets() {
+ return targetMap.keySet().toArray(new String[0]);
+ }
+
+ public static String[] getSources() {
+ return sourceMap.keySet().toArray(new String[0]);
+ }
+
+ public static String[] getPorts() {
+ return portList.toArray(new String[0]);
+ }
+
+ public static TargetDataLine getTargetDataLine(String name) throws LineUnavailableException {
+ if (targetMap.containsKey(name)) {
+ return targetMap.get(name).getLine();
+ } else {
+ throw new LineUnavailableException();
+ }
+ }
+
+ public static TargetDataLine getTargetDataLine(String name, AudioFormat audioFormat) throws LineUnavailableException {
+ if (targetMap.containsKey(name)) {
+ return targetMap.get(name).getLine(audioFormat);
+ } else {
+ throw new LineUnavailableException();
+ }
+ }
+
+ public static SourceDataLine getSourceDataLine(String name) throws LineUnavailableException {
+ if (sourceMap.containsKey(name)) {
+ return sourceMap.get(name).getLine();
+ } else {
+ throw new LineUnavailableException();
+ }
+ }
+
+ public static SourceDataLine getSourceDataLine(String name, AudioFormat audioFormat) throws LineUnavailableException {
+ if (sourceMap.containsKey(name)) {
+ return sourceMap.get(name).getLine(audioFormat);
+ } else {
+ throw new LineUnavailableException();
+ }
+ }
+
+ public class Device {
+ protected Mixer mixer;
+ protected Line.Info lineInfo;
+
+ public Device(Mixer mixer, Line.Info lineInfo) {
+ this.mixer = mixer;
+ this.lineInfo = lineInfo;
+ }
+
+ @SuppressWarnings("unchecked")
+ public T getLine() throws LineUnavailableException {
+ return (T) mixer.getLine(lineInfo);
+ }
+
+ @SuppressWarnings("unchecked")
+ public T getLine(AudioFormat audioFormat) throws LineUnavailableException {
+ DataLine.Info dataLineInfo = new DataLine.Info(lineInfo.getLineClass(), audioFormat);
+ return (T) mixer.getLine(dataLineInfo);
+ }
+ }
+}
diff --git a/java/sound/src/main/java/sound/util/Utils.java b/java/sound/src/main/java/sound/util/Utils.java
new file mode 100644
index 0000000..32100d8
--- /dev/null
+++ b/java/sound/src/main/java/sound/util/Utils.java
@@ -0,0 +1,39 @@
+package sound.util;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import javazoom.jl.decoder.JavaLayerException;
+import javazoom.jl.player.Player;
+
+public class Utils {
+ public static final int BUFFER = 2048; // bytes
+
+ public static void play(InputStream inputStream) {
+ try {
+ new Player(new BufferedInputStream(inputStream)).play();
+ } catch (JavaLayerException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static void write(InputStream inputStream, File file) {
+ byte[] bytes = new byte[BUFFER];
+ int read = 0;
+ try {
+ FileOutputStream fileOutputStream = new FileOutputStream(file);
+ while ((read = inputStream.read(bytes)) > 0) {
+ fileOutputStream.write(bytes, 0, read);
+ }
+ fileOutputStream.close();
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/java/sound/src/main/java/test/SoundAudit.java b/java/sound/src/main/java/test/SoundAudit.java
new file mode 100644
index 0000000..ee44f6a
--- /dev/null
+++ b/java/sound/src/main/java/test/SoundAudit.java
@@ -0,0 +1,55 @@
+package test;
+
+import javax.sound.sampled.*;
+public class SoundAudit {
+ public static void main(String[] args) { try {
+ System.out.println("OS: "+System.getProperty("os.name")+" "+
+ System.getProperty("os.version")+"/"+
+ System.getProperty("os.arch")+"\nJava: "+
+ System.getProperty("java.version")+" ("+
+ System.getProperty("java.vendor")+")\n");
+ for (Mixer.Info thisMixerInfo : AudioSystem.getMixerInfo()) {
+ System.out.println("Mixer: "+thisMixerInfo.getDescription()+
+ " ["+thisMixerInfo.getName()+"]");
+ Mixer thisMixer = AudioSystem.getMixer(thisMixerInfo);
+ for (Line.Info thisLineInfo:thisMixer.getSourceLineInfo()) {
+ if (thisLineInfo.getLineClass().getName().equals(
+ "javax.sound.sampled.Port")) {
+ Line thisLine = thisMixer.getLine(thisLineInfo);
+ thisLine.open();
+ System.out.println(" Source Port: "
+ +thisLineInfo.toString());
+ for (Control thisControl : thisLine.getControls()) {
+ System.out.println(AnalyzeControl(thisControl));}
+ thisLine.close();}}
+ for (Line.Info thisLineInfo:thisMixer.getTargetLineInfo()) {
+ if (thisLineInfo.getLineClass().getName().equals(
+ "javax.sound.sampled.Port")) {
+ Line thisLine = thisMixer.getLine(thisLineInfo);
+ thisLine.open();
+ System.out.println(" Target Port: "
+ +thisLineInfo.toString());
+ for (Control thisControl : thisLine.getControls()) {
+ System.out.println(AnalyzeControl(thisControl));}
+ thisLine.close();}}}
+ } catch (Exception e) {e.printStackTrace();}}
+ public static String AnalyzeControl(Control thisControl) {
+ String type = thisControl.getType().toString();
+ if (thisControl instanceof BooleanControl) {
+ return " Control: "+type+" (boolean)"; }
+ if (thisControl instanceof CompoundControl) {
+ System.out.println(" Control: "+type+
+ " (compound - values below)");
+ String toReturn = "";
+ for (Control children:
+ ((CompoundControl)thisControl).getMemberControls()) {
+ toReturn+=" "+AnalyzeControl(children)+"\n";}
+ return toReturn.substring(0, toReturn.length()-1);}
+ if (thisControl instanceof EnumControl) {
+ return " Control:"+type+" (enum: "+thisControl.toString()+")";}
+ if (thisControl instanceof FloatControl) {
+ return " Control: "+type+" (float: from "+
+ ((FloatControl) thisControl).getMinimum()+" to "+
+ ((FloatControl) thisControl).getMaximum()+")";}
+ return " Control: unknown type";}
+}
diff --git a/java/sound/src/main/java/test/Test.java b/java/sound/src/main/java/test/Test.java
new file mode 100644
index 0000000..067f2bf
--- /dev/null
+++ b/java/sound/src/main/java/test/Test.java
@@ -0,0 +1,45 @@
+package test;
+
+import java.io.File;
+
+import javax.sound.sampled.AudioFormat;
+
+import sound.Consumer;
+import sound.Producer;
+import sound.Source;
+import sound.consumer.Player;
+import sound.consumer.Port;
+import sound.consumer.Shoutcast;
+import sound.consumer.Writer;
+import sound.producer.Stream;
+import sound.producer.Target;
+
+public class Test {
+ public static void main(String[] args) {
+ AudioFormat audioFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 48000f, 16, 2, 4, 48000f, true);
+ try {
+ //Producer p1 = new Target("Line-In (Creative SB X-Fi)");
+ Producer p2 = new Target("Line 1 (Virtual Audio Cable)", audioFormat);
+ p2.start();
+ Producer p3 = new Stream("http://ics2gss.omroep.nl:80/3fm-bb-mp3");
+ Producer p4 = new Stream("http://sc7.mystreamserver.com:8004");
+
+ Consumer c1 = new Source("Java Sound Audio Engine");
+ Consumer c2 = new Port("Speakers (Creative SB X-Fi)");
+ Consumer c3 = new Shoutcast();
+ Consumer c4 = new Player();
+ Consumer c5 = new Writer(new File("stream.out"));
+
+ //Utils.write(p3.getInputStream(), new File("stream.out"));
+ //Utils.play(p3.getInputStream());
+ c3.start(p3);
+
+ //while (true) {
+ //Thread.sleep(300000);
+ //c1.stop();
+ //}
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/sound/src/main/java/test/lines/Main.java b/java/sound/src/main/java/test/lines/Main.java
new file mode 100644
index 0000000..be6bbc2
--- /dev/null
+++ b/java/sound/src/main/java/test/lines/Main.java
@@ -0,0 +1,34 @@
+package test.lines;
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.Line;
+import javax.sound.sampled.LineUnavailableException;
+import javax.sound.sampled.Mixer;
+import javax.sound.sampled.SourceDataLine;
+import javax.sound.sampled.TargetDataLine;
+
+public class Main {
+ public static void main(String[] args) {
+ System.out.println(System.getProperty("javax.sound.sampled.SourceDataLine"));
+
+ new AudioFormat(44100, 16, 2, true, false);
+
+ for (Mixer.Info mixerInfo : AudioSystem.getMixerInfo()) {
+ Mixer mixer = AudioSystem.getMixer(mixerInfo);
+ for (Line.Info lineInfo : mixer.getTargetLineInfo()) {
+ try {
+ Line line = mixer.getLine(lineInfo);
+ if (mixer.isLineSupported(lineInfo)) {
+ if (line instanceof TargetDataLine) {
+ new TargetLine(mixer, (TargetDataLine) line);
+ }/* else if (line instanceof SourceDataLine) {
+ new SourceLine(mixer, (SourceDataLine) line);
+ }*/
+ }
+ } catch (LineUnavailableException e) {}
+ }
+
+ }
+ }
+}
diff --git a/java/sound/src/main/java/test/lines/SourceLine.java b/java/sound/src/main/java/test/lines/SourceLine.java
new file mode 100644
index 0000000..ede5969
--- /dev/null
+++ b/java/sound/src/main/java/test/lines/SourceLine.java
@@ -0,0 +1,19 @@
+package test.lines;
+
+import javax.sound.sampled.Mixer;
+import javax.sound.sampled.SourceDataLine;
+
+public class SourceLine {
+ //private Mixer mixer;
+ private SourceDataLine line;
+
+ public SourceLine(Mixer mixer, SourceDataLine line) {
+ //this.mixer = mixer;
+ this.line = line;
+ System.out.println("SOURCE " + mixer.getMixerInfo().getName() + " || " + line.getLineInfo());
+ }
+
+ public int write(byte[] bytes, int offset, int length) {
+ return line.write(bytes, offset, length);
+ }
+}
diff --git a/java/sound/src/main/java/test/lines/TargetLine.java b/java/sound/src/main/java/test/lines/TargetLine.java
new file mode 100644
index 0000000..e1e7823
--- /dev/null
+++ b/java/sound/src/main/java/test/lines/TargetLine.java
@@ -0,0 +1,19 @@
+package test.lines;
+
+import javax.sound.sampled.Mixer;
+import javax.sound.sampled.TargetDataLine;
+
+public class TargetLine {
+ //private Mixer mixer;
+ private TargetDataLine line;
+
+ public TargetLine(Mixer mixer, TargetDataLine line) {
+ //this.mixer = mixer;
+ this.line = line;
+ System.out.println("TARGET " + mixer.getMixerInfo().getName() + " || " + line.getLineInfo());
+ }
+
+ public int read(byte[] bytes, int offset, int length) {
+ return line.read(bytes, offset, length);
+ }
+}
diff --git a/java/sound/stream.bat b/java/sound/stream.bat
new file mode 100644
index 0000000..21afc51
--- /dev/null
+++ b/java/sound/stream.bat
@@ -0,0 +1 @@
+java -classpath bin udp.StreamClient 234.5.6.7 4567
\ No newline at end of file
diff --git a/java/sound/stream.exe b/java/sound/stream.exe
new file mode 100644
index 0000000..36bf506
Binary files /dev/null and b/java/sound/stream.exe differ
diff --git a/java/sound/stream.jar b/java/sound/stream.jar
new file mode 100644
index 0000000..1d8bbdc
Binary files /dev/null and b/java/sound/stream.jar differ
diff --git a/java/sound/txt/keuze.txt b/java/sound/txt/keuze.txt
new file mode 100644
index 0000000..7e9581d
--- /dev/null
+++ b/java/sound/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/sound/txt/mp3 b/java/sound/txt/mp3
new file mode 100644
index 0000000..daf87ab
--- /dev/null
+++ b/java/sound/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/sound/txt/options b/java/sound/txt/options
new file mode 100644
index 0000000..4d95aae
--- /dev/null
+++ b/java/sound/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 audio/song artist (max 30 chars for version 1 tag)
+ --tl audio/song album (max 30 chars for version 1 tag)
+ --ty audio/song year of issue (1 to 9999)
+ --tc user-defined text (max 30 chars for v1 tag, 28 for v1.1)
+ --tn