summaryrefslogtreecommitdiff
path: root/audio/sysvad/APO/Inc
diff options
context:
space:
mode:
authorGirish Pattabiraman <[email protected]>2018-08-13 10:54:19 -0700
committerAdonais Romero González <[email protected]>2018-08-13 10:54:19 -0700
commit2af3e666d01a60568c2875b4ccbd56b122ad714f (patch)
tree29825a7b7cb0f6a9f77f1ab6e5813665d45ca4cc /audio/sysvad/APO/Inc
parent181c180357cdf9a04d5e3bb21a8e86dc2155ca69 (diff)
Update sample to get ready for RS4 changes - merge pre-RS4 fixes. (#256)
* Format Changes ============== * Add KSEVENT_PINCAPS_FORMATCHANGE to Bluetooth HFP Endpoints * Remove 8 bit formats from Bluetooth HFP Endpoints Name Template ============== * Bluetooth Endpoints are now based on templates in INF and then customized with endpoints specific data Sideband Common Interface for future Sideband buses =================================================== * Add ISidebandDevice * Add current directory to TabletAudioSample include path. Remove unused compiler flags. * RS4 bug fixes
Diffstat (limited to 'audio/sysvad/APO/Inc')
-rw-r--r--audio/sysvad/APO/Inc/CommonMacros.h337
-rw-r--r--audio/sysvad/APO/Inc/CustomPropKeys.h39
-rw-r--r--audio/sysvad/APO/Inc/tlist.h476
3 files changed, 852 insertions, 0 deletions
diff --git a/audio/sysvad/APO/Inc/CommonMacros.h b/audio/sysvad/APO/Inc/CommonMacros.h
new file mode 100644
index 00000000..097c6d47
--- /dev/null
+++ b/audio/sysvad/APO/Inc/CommonMacros.h
@@ -0,0 +1,337 @@
+//**@@@*@@@****************************************************
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+//**@@@*@@@****************************************************
+
+//
+// FileName: CommonMacros.h
+//
+// Abstract: Useful macros
+//
+// ----------------------------------------------------------------------------
+
+
+#pragma once
+#include <windef.h>
+#include <windows.h>
+
+
+//-------------------------------------------------------------------------
+// Description:
+//
+// If the condition evaluates to TRUE, jump to the given label.
+//
+// Parameters:
+//
+// condition - [in] code that fits in if statement
+// label - [in] label to jump if condition is met
+//
+#define IF_TRUE_JUMP(condition, label) \
+ if (condition) \
+ { \
+ goto label; \
+ }
+
+//-------------------------------------------------------------------------
+// Description:
+//
+// If the condition evaluates to FALSE, jump to the given label.
+//
+// Parameters:
+//
+// condition - [in] code that fits in if statement
+// label - [in] label to jump if condition is met
+//
+#define IF_FALSE_JUMP(condition, label) \
+ if (!condition) \
+ { \
+ goto label; \
+ }
+
+//-------------------------------------------------------------------------
+// Description:
+//
+// If the hresult passed FAILED, jump to the given label.
+//
+// Parameters:
+//
+// _hresult - [in] Value to check
+// label - [in] label to jump if condition is met
+//
+#define IF_FAILED_JUMP(_hresult, label) \
+ if (FAILED(_hresult)) \
+ { \
+ goto label; \
+ }
+
+//-------------------------------------------------------------------------
+// Description:
+//
+// If the hresult passed SUCCEEDED, jump to the given label.
+//
+// Parameters:
+//
+// _hresult - [in] Value to check
+// label - [in] label to jump if condition is met
+//
+#define IF_SUCCEEDED_JUMP(_hresult, label) \
+ if (SUCCEEDED(_hresult)) \
+ { \
+ goto label; \
+ }
+
+//-------------------------------------------------------------------------
+// Description:
+//
+// If the condition evaluates to TRUE, perform the given statement
+// then jump to the given label.
+//
+// Parameters:
+//
+// condition - [in] Code that fits in if statement
+// action - [in] action to perform in body of if statement
+// label - [in] label to jump if condition is met
+//
+#define IF_TRUE_ACTION_JUMP(condition, action, label) \
+ if (condition) \
+ { \
+ action; \
+ goto label; \
+ }
+
+//-------------------------------------------------------------------------
+// Description:
+//
+// If the hresult FAILED, perform the given statement then jump to
+// the given label.
+//
+// Parameters:
+//
+// _hresult - [in] Value to check
+// action - [in] action to perform in body of if statement
+// label - [in] label to jump if condition is met
+//
+#define IF_FAILED_ACTION_JUMP(_hresult, action, label) \
+ if (FAILED(_hresult)) \
+ { \
+ action; \
+ goto label; \
+ }
+
+//-------------------------------------------------------------------------
+// Description:
+//
+// Closes a handle and assigns NULL.
+//
+// Parameters:
+//
+// h - [in] handle to close
+//
+#define SAFE_CLOSE_HANDLE(h) \
+ if (NULL != h) \
+ { \
+ CloseHandle(h); \
+ h = NULL; \
+ }
+
+//-------------------------------------------------------------------------
+// Description:
+//
+// Addref an interface pointer
+//
+// Parameters:
+//
+// p - [in] object to addref
+//
+#define SAFE_ADDREF(p) \
+ if (NULL != p) \
+ { \
+ (p)->AddRef();; \
+ }
+
+//-------------------------------------------------------------------------
+// Description:
+//
+// Releases an interface pointer and assigns NULL.
+//
+// Parameters:
+//
+// p - [in] object to release
+//
+#define SAFE_RELEASE(p) \
+ if (NULL != p) \
+ { \
+ (p)->Release(); \
+ (p) = NULL; \
+ }
+
+//-------------------------------------------------------------------------
+// Description:
+//
+// Deletes a pointer and assigns NULL. Do not check for NULL because
+// the default delete operator checks for it.
+//
+// Parameters:
+//
+// p - [in] object to delete
+//
+#define SAFE_DELETE(p) \
+ delete p; \
+ p = NULL;
+
+//-------------------------------------------------------------------------
+// Description:
+//
+// Deletes an array pointer and assigns NULL. Do not check for NULL because
+// the default delete operator checks for it.
+//
+// Parameters:
+//
+// p - [in] Array to delete
+//
+#define SAFE_DELETE_ARRAY(p) \
+ delete [] p; \
+ p = NULL;
+
+//-------------------------------------------------------------------------
+// Description:
+//
+// Frees a block of memory allocated by CoTaskMemAlloc and assigns NULL to
+// the pointer
+//
+// Parameters:
+//
+// p - [in] Pointer to memory to free
+//
+#define SAFE_COTASKMEMFREE(p) \
+ if (NULL != p) \
+ { \
+ CoTaskMemFree(p); \
+ (p) = NULL; \
+ }
+
+//-------------------------------------------------------------------------
+// Description:
+//
+// Frees a DLL loaded with LoadLibrary and assigns NULL to the handle
+//
+// Parameters:
+//
+// h - [in] Handle to DLL to free
+//
+#define SAFE_FREELIBRARY(h) \
+ if (NULL != h) \
+ { \
+ FreeLibrary(h); \
+ (h) = NULL; \
+ }
+
+//-------------------------------------------------------------------------
+// Description:
+//
+// Used to validate a read pointer
+//
+// Parameters:
+//
+// p - [in] read pointer.
+// s - [in] size of memory in bytes pointed to by p.
+//
+#define IS_VALID_READ_POINTER(p, s) ((NULL != p) || (0 == s))
+
+//-------------------------------------------------------------------------
+// Description:
+//
+// Used to validate a write pointer
+//
+// Parameters:
+//
+// p - [in] write pointer.
+// s - [in] size of memory in bytes pointed to by p.
+//
+#define IS_VALID_WRITE_POINTER(p, s) ((NULL != p) || (0 == s))
+
+//-------------------------------------------------------------------------
+// Description:
+//
+// Used to validate a read pointer of a particular type
+//
+// Parameters:
+//
+// p - [in] typed read pointer
+//
+#define IS_VALID_TYPED_READ_POINTER(p) IS_VALID_READ_POINTER((p), sizeof *(p))
+
+//-------------------------------------------------------------------------
+// Description:
+//
+// Used to validate a write pointer of a particular type
+//
+// Parameters:
+//
+// p - [in] typed write pointer
+//
+#define IS_VALID_TYPED_WRITE_POINTER(p) IS_VALID_WRITE_POINTER((p), sizeof *(p))
+
+// ---------------------------------------------------------------------------
+// Macros that wrap windows messages. Similar to those in windowsX.h and
+// commctrl.h
+//
+#if !defined Static_SetIcon
+#define Static_SetIcon(hwnd, hi) \
+ (BOOL)SNDMSG((hwnd), STM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)(hi))
+#endif
+
+#define TrackBar_SetTickFrequency(hwnd, f) \
+ (BOOL)SNDMSG((hwnd), TBM_SETTICFREQ, (WPARAM)(f), 0)
+
+#define TrackBar_SetBuddy(hwnd, f, hbud) \
+ (HWND)SNDMSG((hwnd), TBM_SETBUDDY, (WPARAM)(f), (LPARAM)hbud)
+
+#define TrackBar_GetPos(hwnd) \
+ (int)SNDMSG((hwnd), TBM_GETPOS, 0, 0)
+
+#define TrackBar_SetPos(hwnd, pos) \
+ SNDMSG((hwnd), TBM_SETPOS, (WPARAM)TRUE, (LPARAM)pos)
+
+#define TrackBar_SetRange(hwnd, min, max) \
+ SNDMSG((hwnd), TBM_SETRANGE , (WPARAM)TRUE, (LPARAM) MAKELONG(min, max))
+
+#define TrackBar_SetThumbLength(hwnd, l) \
+ SNDMSG((hwnd), TBM_SETTHUMBLENGTH, (WPARAM)l, 0);
+
+#define TrackBar_SetPageSize(hwnd, n) \
+ SNDMSG((hwnd), TBM_SETPAGESIZE, 0, (LPARAM)n)
+
+#define Window_GetFont(hwnd) \
+ (HFONT)SNDMSG((hwnd), WM_GETFONT, 0, 0)
+
+#define Window_SetFont(hwnd, font) \
+ SNDMSG((hwnd), WM_SETFONT, (WPARAM)font, FALSE)
+
+
+// ----------------------------------------------------------------------
+// A struct for holding a rect in easier terms than a RECT struct
+//
+struct SRECT
+{
+ int x, y, w, h;
+ SRECT()
+ {
+ x = y = w = h = 0;
+ }
+ SRECT(int X, int Y, int W, int H)
+ {
+ x = X; y = Y; w = W; h = H;
+ }
+ SRECT(RECT* prc)
+ {
+ x = prc->left;
+ y = prc->top;
+ w = prc->right - prc->left;
+ h = prc->bottom - prc->top;
+ }
+};
+
+#define HNS_PER_SECOND (10ull * 1000ull * 1000ull)
diff --git a/audio/sysvad/APO/Inc/CustomPropKeys.h b/audio/sysvad/APO/Inc/CustomPropKeys.h
new file mode 100644
index 00000000..dab286a5
--- /dev/null
+++ b/audio/sysvad/APO/Inc/CustomPropKeys.h
@@ -0,0 +1,39 @@
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+#pragma once
+
+// header files for imported files
+#include "propidl.h"
+
+#ifdef DEFINE_PROPERTYKEY
+#undef DEFINE_PROPERTYKEY
+#endif
+
+#ifdef INITGUID
+#define DEFINE_PROPERTYKEY(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8, pid) EXTERN_C const PROPERTYKEY name = { { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }, pid }
+#else
+#define DEFINE_PROPERTYKEY(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8, pid) EXTERN_C const PROPERTYKEY name
+#endif // INITGUID
+
+// ----------------------------------------------------------------------
+//
+// PKEY_Endpoint_Enable_Channel_Swap_SFX: When value is 0x00000001, Channel Swap local effect is enabled
+// {A44531EF-5377-4944-AE15-53789A9629C7},2
+// vartype = VT_UI4
+DEFINE_PROPERTYKEY(PKEY_Endpoint_Enable_Channel_Swap_SFX, 0xa44531ef, 0x5377, 0x4944, 0xae, 0x15, 0x53, 0x78, 0x9a, 0x96, 0x29, 0xc7, 2);
+
+// PKEY_Endpoint_Enable_Channel_Swap_MFX: When value is 0x00000001, Channel Swap global effect is enabled
+// {A44531EF-5377-4944-AE15-53789A9629C7},3
+// vartype = VT_UI4
+DEFINE_PROPERTYKEY(PKEY_Endpoint_Enable_Channel_Swap_MFX, 0xa44531ef, 0x5377, 0x4944, 0xae, 0x15, 0x53, 0x78, 0x9a, 0x96, 0x29, 0xc7, 3);
+
+// PKEY_Endpoint_Enable_Delay_SFX: When value is 0x00000001, Delay local effect is enabled
+// {A44531EF-5377-4944-AE15-53789A9629C7},4
+// vartype = VT_UI4
+DEFINE_PROPERTYKEY(PKEY_Endpoint_Enable_Delay_SFX, 0xa44531ef, 0x5377, 0x4944, 0xae, 0x15, 0x53, 0x78, 0x9a, 0x96, 0x29, 0xc7, 4);
+
+// PKEY_Endpoint_Enable_Delay_MFX: When value is 0x00000001, Delay global effect is enabled
+// {A44531EF-5377-4944-AE15-53789A9629C7},5
+// vartype = VT_UI4
+DEFINE_PROPERTYKEY(PKEY_Endpoint_Enable_Delay_MFX, 0xa44531ef, 0x5377, 0x4944, 0xae, 0x15, 0x53, 0x78, 0x9a, 0x96, 0x29, 0xc7, 5);
diff --git a/audio/sysvad/APO/Inc/tlist.h b/audio/sysvad/APO/Inc/tlist.h
new file mode 100644
index 00000000..6c0479aa
--- /dev/null
+++ b/audio/sysvad/APO/Inc/tlist.h
@@ -0,0 +1,476 @@
+//**@@@*@@@****************************************************
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//
+//**@@@*@@@****************************************************
+
+//
+// FileName: tlist.h
+//
+// Abstract: This is the header and implementation file for a template
+// list class
+//
+// ----------------------------------------------------------------------------
+
+#pragma once
+
+
+typedef void* LISTPOS;
+
+template <class T>
+class TItem
+{
+public:
+ TItem() throw();
+ ~TItem() throw();
+ TItem<T> * pNext;
+ TItem<T> * pPrev;
+ T* pData;
+};
+
+template <class T>
+TItem<T>::TItem() :
+ pNext(NULL),
+ pPrev(NULL),
+ pData(NULL)
+{
+ return;
+}
+
+template <class T>
+TItem<T>::~TItem()
+{
+ return;
+}
+
+
+template <class T>
+class TList
+{
+ public:
+ TList() throw();
+ ~TList() throw();
+
+ BOOL GetHead( T** ppHead ) const throw();
+ LISTPOS GetHeadPosition() const throw();
+ LISTPOS GetTailPosition() const throw();
+ LISTPOS AddHead(__drv_aliasesMem T* pNewHead) throw();
+ LISTPOS AddTail(__drv_aliasesMem T* pNewTail) throw();
+ BOOL RemoveTail(T** ppOldTail) throw();
+ BOOL RemoveHead(T** ppOldHead) throw();
+ void RemoveAll() throw();
+ LISTPOS Find( T* pSearchValue ) const throw();
+ void RemoveAt(LISTPOS pos) throw();
+ BOOL GetNext(LISTPOS& rPos, T**ppThisData) const throw();
+ BOOL IsEmpty() const throw();
+ DWORD GetCount() const throw();
+ HRESULT Initialize(DWORD dwValue) throw();
+ BOOL GetAt( LONG index, T** ppElement) const throw();
+ BOOL GetAt( LISTPOS pos, T** ppElement) const throw();
+ LISTPOS InsertBefore(LISTPOS pos, T* pNewElement) throw();
+ LISTPOS InsertAfter(LISTPOS pos, T* pNewElement) throw();
+ void MoveHeadList(TList<T> *pFromList) throw();
+private:
+ TItem<T>* m_pHead;
+ TItem<T>* m_pTail;
+ LONG m_lCount;
+};
+
+template <class T>
+TList<T>::TList() :
+ m_pHead(NULL),
+ m_pTail(NULL),
+ m_lCount(0)
+{
+ return;
+}
+
+template <class T>
+TList<T>::~TList()
+{
+ ATLASSERT(NULL == m_pHead);
+ ATLASSERT(NULL == m_pTail);
+ ATLASSERT(0 == m_lCount);
+ return;
+}
+
+template <class T>
+BOOL TList<T>::GetHead(T** ppHead) const
+{
+ if (!m_pHead)
+ {
+ *ppHead = NULL;
+ return FALSE;
+ }
+
+ *ppHead = m_pHead->pData;
+ return TRUE;
+}
+
+template <class T>
+LISTPOS TList<T>::GetHeadPosition() const
+{
+ return reinterpret_cast<LISTPOS>(m_pHead);
+}
+
+template <class T>
+LISTPOS TList<T>::GetTailPosition() const
+{
+ return reinterpret_cast<LISTPOS>(m_pTail);
+}
+
+template <class T>
+LISTPOS TList<T>::AddTail(__drv_aliasesMem T* pNewTail)
+{
+ TItem<T>* pNewItem;
+
+ pNewItem = new TItem<T>;
+ if (NULL == pNewItem)
+ {
+ return( reinterpret_cast<LISTPOS>( NULL ));
+ }
+
+ pNewItem->pData = pNewTail;
+ pNewItem->pPrev = m_pTail;
+ pNewItem->pNext = NULL;
+
+ if (NULL == m_pTail)
+ {
+ m_pHead = pNewItem;
+ }
+ else
+ {
+ m_pTail->pNext = pNewItem;
+ }
+
+ m_pTail = pNewItem;
+ m_lCount++;
+
+ return( reinterpret_cast<LISTPOS>( pNewItem ) );
+}
+
+template <class T>
+LISTPOS TList<T>::AddHead(__drv_aliasesMem T* pNewHead)
+{
+ TItem<T> *pNewItem;
+ pNewItem = new TItem<T>;
+ if ( !pNewItem )
+ {
+ return( reinterpret_cast<LISTPOS>( NULL ) );
+ }
+
+ pNewItem->pData = pNewHead;
+ pNewItem->pNext = m_pHead;
+ pNewItem->pPrev = NULL;
+
+ if ( NULL != m_pHead )
+ {
+ m_pHead->pPrev = pNewItem;
+ }
+ else
+ {
+ m_pTail = pNewItem;
+ }
+
+ m_pHead = pNewItem;
+ m_lCount++;
+
+ return( reinterpret_cast<LISTPOS>( pNewItem ) );
+}
+
+template <class T>
+void TList<T>::MoveHeadList(TList<T> *pFromList)
+{
+ // Link head item of this list to tail item of other list
+ if (NULL != m_pHead)
+ m_pHead->pPrev = pFromList->m_pTail;
+ if (NULL != pFromList->m_pTail)
+ pFromList->m_pTail->pNext = m_pHead;
+
+ // Adjust this list's head and tail pointers
+ if (pFromList->m_pHead)
+ m_pHead = pFromList->m_pHead;
+ if (NULL == m_pTail)
+ m_pTail = pFromList->m_pTail;
+
+ // Adjust this list's count
+ m_lCount += pFromList->m_lCount;
+
+ // Reset other list's head and tail pointers and count
+ pFromList->m_pHead = NULL;
+ pFromList->m_pTail = NULL;
+ pFromList->m_lCount = 0;
+}
+
+template <class T>
+BOOL TList<T>::RemoveTail( T** ppOldTail)
+{
+
+ if (!ppOldTail || !m_pTail)
+ {
+ return FALSE;
+ }
+
+ TItem<T> *pOldItem = m_pTail;
+ *ppOldTail = pOldItem->pData;
+
+ m_pTail = pOldItem->pPrev;
+
+ if ( NULL != m_pTail )
+ {
+ m_pTail->pNext = NULL;
+ }
+ else
+ {
+ m_pHead = NULL;
+ }
+
+ delete pOldItem;
+ m_lCount--;
+ ATLASSERT(m_lCount >= 0);
+
+ return( TRUE );
+}
+
+template <class T>
+BOOL TList<T>::RemoveHead(T** ppOldHead)
+{
+ if ( !ppOldHead || !m_pHead )
+ {
+ return( FALSE );
+ }
+
+ TItem<T> *pOldItem = m_pHead;
+ *ppOldHead = pOldItem->pData;
+
+ m_pHead = pOldItem->pNext;
+
+ if ( NULL != m_pHead )
+ {
+ m_pHead->pPrev = NULL;
+ }
+ else
+ {
+ m_pTail = NULL;
+ }
+
+ delete pOldItem;
+ m_lCount--;
+ ATLASSERT(m_lCount >= 0);
+
+ return( TRUE );
+}
+
+template <class T>
+void TList<T>::RemoveAll()
+{
+ TItem<T> *pNext;
+
+ while( NULL != m_pHead )
+ {
+ pNext = m_pHead->pNext;
+ delete m_pHead;
+ m_pHead = pNext;
+ }
+
+ m_lCount = 0;
+ m_pTail = NULL;
+
+ return;
+}
+
+template <class T>
+LISTPOS TList<T>::Find( T* pSearchValue ) const
+{
+ TItem<T> *pItem = m_pHead;
+
+ for ( ; NULL != pItem; pItem = pItem->pNext )
+ {
+ if ( pItem->pData == pSearchValue )
+ {
+ return( reinterpret_cast<LISTPOS>(pItem) );
+ }
+ }
+
+ return( reinterpret_cast<LISTPOS>(NULL) );
+}
+
+template <class T>
+void TList<T>::RemoveAt(LISTPOS pos)
+{
+ // ATLASSERT( NULL != pos )
+ TItem<T> *pOldItem = reinterpret_cast< TItem<T>* >(pos);
+
+ // remove pOldItem from list
+ if ( pOldItem == m_pHead )
+ {
+ m_pHead = pOldItem->pNext;
+ }
+ else
+ {
+ ATLASSERT( pOldItem->pPrev );
+ pOldItem->pPrev->pNext = pOldItem->pNext;
+ }
+
+ if (pOldItem == m_pTail)
+ {
+ m_pTail = pOldItem->pPrev;
+ }
+ else
+ {
+ ATLASSERT( pOldItem->pNext );
+ pOldItem->pNext->pPrev = pOldItem->pPrev;
+ }
+
+ delete pOldItem;
+ m_lCount--;
+ ATLASSERT(m_lCount >= 0);
+ return;
+}
+
+template <class T>
+BOOL TList<T>::GetNext(LISTPOS& rPos, T**ppThisData) const
+{
+ TItem<T> *pItem = reinterpret_cast< TItem<T>* >(rPos);
+
+ if ( !pItem )
+ {
+ return( FALSE );
+ }
+
+ rPos = reinterpret_cast<LISTPOS>(pItem->pNext);
+ if (ppThisData)
+ {
+ *ppThisData = pItem->pData;
+ }
+
+ return( TRUE );
+}
+
+template <class T>
+BOOL TList<T>::IsEmpty() const
+{
+ return (0 == m_lCount);
+}
+
+template <class T>
+HRESULT TList<T>::Initialize(DWORD dwValue)
+{
+ HRESULT hr = S_OK;
+ return hr;
+}
+
+template <class T>
+DWORD TList<T>::GetCount() const
+{
+ return static_cast<DWORD>(m_lCount);
+}
+
+
+template <class T>
+LISTPOS TList<T>::InsertBefore(LISTPOS pos, T* pNewElement)
+{
+ TItem<T>* pOldItem = reinterpret_cast<TItem<T>*>(pos);
+ TItem<T>* pNewItem;
+
+ if ((pOldItem == NULL) || (pOldItem->pPrev == NULL))
+ {
+ return (AddHead(pNewElement)); // insert before nothing -> head of the list
+ }
+
+ // Insert it before pos
+ pNewItem = new TItem<T>;
+ if (!pNewItem)
+ {
+ return (reinterpret_cast<LISTPOS>(NULL));
+ }
+
+ pNewItem->pData = pNewElement;
+ pNewItem->pPrev = pOldItem->pPrev;
+ pNewItem->pNext = pOldItem;
+
+ pOldItem->pPrev->pNext = pNewItem;
+ pOldItem->pPrev = pNewItem;
+
+ m_lCount++;
+
+ return (reinterpret_cast<LISTPOS>(pNewItem));
+}
+
+template <class T>
+LISTPOS TList<T>::InsertAfter(LISTPOS pos, T* pNewElement)
+{
+ TItem<T>* pOldItem = reinterpret_cast<TItem<T>*>(pos);
+ TItem<T>* pNewItem;
+
+ if ((pOldItem == NULL) || (pOldItem->pNext == NULL))
+ {
+ return (AddTail(pNewElement)); // insert after nothing -> tail of the list
+ }
+
+ // Insert it after pos
+ pNewItem = new TItem<T>;
+ if (!pNewItem)
+ {
+ return (reinterpret_cast<LISTPOS>(NULL));
+ }
+
+ pNewItem->pData = pNewElement;
+ pNewItem->pPrev = pOldItem;
+ pNewItem->pNext = pOldItem->pNext;
+
+ pOldItem->pNext->pPrev = pNewItem;
+ pOldItem->pNext = pNewItem;
+
+ m_lCount++;
+
+ return (reinterpret_cast<LISTPOS>(pNewItem));
+}
+
+template <class T>
+BOOL TList<T>::GetAt( LONG index, T** ppElement) const
+{
+ if (ppElement == NULL)
+ {
+ return false;
+ }
+
+ *ppElement = NULL;
+
+ if ((index < 0) || (index > (m_lCount - 1)))
+ {
+ return false;
+ }
+
+ T* pElement = NULL;
+ BOOL bRes = TRUE;
+ LISTPOS pos = GetHeadPosition();
+
+ for (int i = 0; bRes && (i <= index); i++)
+ {
+ bRes = GetNext(pos, &pElement);
+ }
+
+ if (bRes)
+ {
+ *ppElement = pElement;
+ }
+
+ return bRes;
+}
+
+template <class T>
+BOOL TList<T>::GetAt(LISTPOS pos, T**ppThisData) const
+{
+ TItem<T> *pItem = reinterpret_cast< TItem<T>* >(pos);
+
+ if ( !pItem )
+ {
+ return( FALSE );
+ }
+
+ *ppThisData = pItem->pData;
+
+ return( TRUE );
+}