// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 
// PARTICULAR PURPOSE.
//
// Copyright © 1993, 1994  Microsoft Corporation.  All Rights Reserved.
//
//	LIBRARY     TLSDLL.DLL
//
//	PURPOSE:	Win32 DLL to manage thread local storage.
//
//	PLATFORMS:	Chicago, NT, Win32s
//
//	FUNCTIONS:	
//
//	SPECIAL INSTRUCTIONS: N/A
//


#include "windows.h"
#include "stdlib.h"
#include "malloc.h"

//#include "string.h"
//#include "stdio.h"
#include "tlsdll.h"

#define TLS_MINIMUM_AVAILABLE 64

DWORD TlsIndex;        /* Global TLS index */
int TlsCount=0;        /* a counter for data in TLS storage */
char chTlsCount[3];    /* string for counter values */


/*-----------------------------------------------------------------*/

INT WINAPI DllMain(HANDLE hInst, ULONG ul_reason_being_called, LPVOID lpReserved)

/*
Purpose: Is called upon entering a dll or detaching
         from a DLL.  This function does most of the TLS manipulation.

Inputs:  hInst - not used
         ul_reason_being_called - reason DllMain is called


Returns: N/A

Calls:   TlsAlloc - allocate a TLS index
         malloc - allocate space for tls storage
         TlsSetValue - Store TLS values
         TlsFree - free TLS index
         TlsRetreive - retreives TLS values, based on index
*/

{

LPVOID TlsString;  /* TLS string for storage */


UNREFERENCED_PARAMETER(hInst);
UNREFERENCED_PARAMETER(lpReserved);


switch (ul_reason_being_called)
  {
  OutputDebugString( "***************TlsDll: DllMain()...\r\n" );
  case DLL_PROCESS_ATTACH:           /* process attaches         */
    OutputDebugString( "***************DLL_PROCESS_ATTACH...\r\n" );
    TlsIndex= TlsAlloc();            /* create TLS index         */
    if (TlsIndex == 0xFFFFFFFF)
      MessageBox( NULL, "TlsAlloc() failed.", "MltiThrd", MB_OK );
    break;

  case DLL_THREAD_ATTACH:            /* thread attaches          */

    OutputDebugString( "***************DLL_THREAD_ATTACH...\r\n" );
    if (!(DLL_PROCESS_ATTACH & ul_reason_being_called))
    {
        OutputDebugString( "***************Allocating memory...\r\n" );
        TlsCount++;
        TlsString= malloc(100);          /* allocate storage         */

        wsprintf( TlsString, "Tls Thread# %d", TlsCount );

        if (!TlsSetValue(TlsIndex,        /* set TLS value            */
                        TlsString))
          MessageBox( NULL, "TlsSetValue() failed.", "MltiThrd", MB_OK );
    }
    break;

  case DLL_THREAD_DETACH:            /* thread detaches          */
    OutputDebugString( "***************DLL_THREAD_DETACH...\r\n" );
//    printf("Thread Detaching\n");
//  TlsRetreive ();           /* retreive TLS data        */
    break;

  case DLL_PROCESS_DETACH:           /* process detaches         */
    OutputDebugString( "***************DLL_PROCESS_DETACH...\r\n" );
    if (!TlsFree(TlsIndex))          /* free TLS index           */
      MessageBox( NULL, "TlsFree() failed.", "MltiThrd", MB_OK );
    break;


  default:
    break;
  }

return 1;
}

/****************************************************************************/

INT WINAPI TlsInit()

/*
Purpose: Allow LibMain to be executed for each thread

Inputs:  none

Returns: none

Calls:   none
*/

{
    OutputDebugString( "***************TlsDll: TlsInit()...\r\n" );

return 1;
}

/****************************************************************************/

LPVOID WINAPI TlsRetreive( )

/*
Purpose: Retreive TLS values and display (printf) them

Inputs:  TlsIndex - TLS index value

Returns: none

Calls:   TlsGetValue - Gets the TLS value from the index
                       based on the current thread.
*/

{
    LPVOID tlsvals;

    OutputDebugString( "***************TlsRetreive()...\r\n" );

    (LPVOID)tlsvals= TlsGetValue(TlsIndex);   /* get the TLS value */

    if (tlsvals == 0)
    {
        MessageBox( NULL, "TlsGetValue() failed.", "MltiThrd", MB_OK );
        return 0;
    }

    return tlsvals;
}


/****************************************************************************/

BOOL WINAPI TlsSet( LPSTR lpstr )

/*
Purpose: Allow setting of tls value for thread

Inputs:  LPSTR lpstr = value to set tls buffer to

Returns: TRUE   - success
         FALSE  - failure


Calls:   TlsSetValue.

Comments:
        Since this uses a global index you really don't get per
        thread tls values.  This will be corrected in future versions.

*/

{
    BOOL fRet;
    LPSTR pszDup;

    if ( lpstr != NULL ) {
        pszDup = strdup ( lpstr );

        OutputDebugString( "***************TlsSet: TlsSetValue()...\r\n" );

        if ( pszDup != NULL ) {
            fRet = TlsSetValue ( TlsIndex, lpstr );
        }
    }

    return fRet;

}

/****************************************************************************/
