//Sample code file: var/ndk/webBuildengine/tmp/viewable_samples/a4ad0b48-dd95-46b6-8289-721e99c8dc76/nmas_client/idplugin.c

//Warning: This code has been marked up for HTML

/*
 *****************************************************************************
 *
 * (C) Copyright 2002 by Novell, Inc.  All Rights Reserved.
 *
 * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES.
 * USE AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO THE LICENSE AGREEMENT
 * ACCOMPANYING THE SOFTWARE DEVELOPMENT KIT (SDK) THAT CONTAINS THIS WORK.
 * PURSUANT TO THE SDK LICENSE AGREEMENT, NOVELL HEREBY GRANTS TO DEVELOPER A
 * ROYALTY-FREE, NON-EXCLUSIVE LICENSE TO INCLUDE NOVELL'S SAMPLE CODE IN ITS
 * PRODUCT. NOVELL GRANTS DEVELOPER WORLDWIDE DISTRIBUTION RIGHTS TO MARKET,
 * DISTRIBUTE, OR SELL NOVELL'S SAMPLE CODE AS A COMPONENT OF DEVELOPER'S
 * PRODUCTS. NOVELL SHALL HAVE NO OBLIGATIONS TO DEVELOPER OR DEVELOPER'S
 * CUSTOMERS WITH RESPECT TO THIS CODE.
 *
 *****************************************************************************
*/

/* *************************************************************************** */
/* This is sample code for implementind a User ID Plugin with the NMAS Client. */
/* A user ID plugin should read data from an authentication device and         */
/* The fields in the login dialog based on that data.                     */
/*                                                            */
/* This example reads data from the registry instead of a device. In order for */
/* this sample code to work, you will need to create the following registry    */
/* key:                                                         */
/* HKLM\SOFTWARE\Novell\NMAS\MethodData\IDPluginExample                     */
/*                                                            */
/* Under this key you may add the following string values containing         */ 
/* information for the login dialog:                                 */
/* Username                                                      */
/* Context                                                      */
/* Tree                                                         */
/* Server                                                      */
/* Sequence                                                      */
/* Clearance                                                   */
/*                                                            */
/* Also, this DLL must be registered as the ID Plugin for the NMAS Client. To  */
/* register it, set the following value in the registry:                  */
/* Key: HKLM\SOFTWARE\Novell\NMAS\1.0\ID                              */
/* Value Name; IDDLLPath                                          */
/* Type: String                                                   */
/* Value Data: Path and name of this DLL                              */
/* *************************************************************************** */

class='cKeyword'>#include <windows.h>
class='cKeyword'>#include <unicode.h>
class='cKeyword'>#include <nmaslogininfo.h>

class='cKeyword'>#define BUFFER_LEN 256

static HANDLE threadExitedEvent = INVALID_HANDLE_VALUE;
static HANDLE threadHandle = INVALID_HANDLE_VALUE;
static LPFN_NMAS_SetLoginIdentity NMAS_SetLoginIdentity = NULL;

/*****************************************************************************/
int localToUnicode(unicode *u, class='cKeyword'>char *s)
{
   nptr      localHandle;
   nint      err;
   nuint32   len;

   err = NWGetLocalToUnicodeHandle(&localHandle);
   
   if(err)
   {
      *u = L'\0';
      return err;
   }
   
   err = NWLocalToUnicode(localHandle, (punicode) u, (nuint32) strlen(s) + 1, (unsigned class='cKeyword'>char*)s, L'*', (unsigned int*) &len);

   if(err)
   {
      *u = L'\0';
   }
   
   return err;
}   

/* ******************************************************************* */
int getIDValue(class='cKeyword'>char *valueName, class='cKeyword'>char *valueData, int valueDataLen)
{
   int err = 0;
   HKEY hKey = 0;
   DWORD type, dataSize;

   err = RegOpenKeyEx(HKEY_LOCAL_MACHINE, 
                  "SOFTWARE\\Novell\\NMAS\\MethodData\\IDPluginExample",
                  0,
                  KEY_QUERY_VALUE,
                  &hKey);
   if(!err)
   {
      dataSize = valueDataLen;
      err = RegQueryValueEx(hKey, valueName, 0, &type, (BYTE*)valueData, &dataSize);
   }

   if(hKey)
      RegCloseKey(hKey);

   return err;
}

/* ******************************************************************* */
/* This is the thread that monitors the device.                     */
/* ******************************************************************* */
DWORD APIENTRY getUserInfoFromDevice(void *param)
{
   int err = 0;
   class='cKeyword'>char data[BUFFER_LEN];
   NMAS_LOGIN_IDENTITY identity;

   /* This example reads the login information from the registry. */

   memset(&identity, 0, sizeof(NMAS_LOGIN_IDENTITY));
   identity.size = sizeof(NMAS_LOGIN_IDENTITY);   

   identity.validFields = 0;

   if(!getIDValue("Username", data, BUFFER_LEN))
   {
      localToUnicode(identity.userName, data);
      identity.validFields |= NLI_FIELD_USERNAME;
   }

   if(!getIDValue("Context", data, BUFFER_LEN))
   {
      localToUnicode(identity.context, data);
      identity.validFields |= NLI_FIELD_CONTEXT;
   }

   if(!getIDValue("Sequence", data, BUFFER_LEN))
   {
      localToUnicode(identity.sequence, data);
      identity.validFields |= NLI_FIELD_SEQUENCE;
   }

   if(!getIDValue("Clearance", data, BUFFER_LEN))
   {
      localToUnicode(identity.clearance, data);
      identity.validFields |= NLI_FIELD_CLEARANCE;
   }

   if(!getIDValue("Server", data, BUFFER_LEN))
   {
      localToUnicode(identity.server, data);
      identity.validFields |= NLI_FIELD_SERVER;
   }

   if(!getIDValue("Tree", data, BUFFER_LEN))
   {
      localToUnicode(identity.tree, data);
      identity.validFields |= NLI_FIELD_TREE;
   }

   if(NMAS_SetLoginIdentity)
      NMAS_SetLoginIdentity(&identity);
      
   SetEvent(threadExitedEvent);

   return err;
}

/* ******************************************************************* */
/* The login dialog will call this function when your code should      */
/* start monitoring its device.                                 */
/* ******************************************************************* */
int StartIdentityPlugin()
{
   DWORD threadId;

   if(threadExitedEvent == INVALID_HANDLE_VALUE)
   {
      threadExitedEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
      if(threadExitedEvent && threadExitedEvent != INVALID_HANDLE_VALUE)
      {
         threadHandle = CreateThread(NULL,0, &getUserInfoFromDevice, NULL, 0, &threadId);
      }
   }

   return 0;
}

/* ******************************************************************* */
/* The login dialog will call this function when your code should      */
/* stop monitoring its device.                                 */
/* ******************************************************************* */
int StopIdentityPlugin()
{
   if(threadExitedEvent && threadExitedEvent != INVALID_HANDLE_VALUE)
   {   
      /* Make sure the thead reading the device exits before this DLL gets unloaded... */
      WaitForSingleObject(threadExitedEvent, INFINITE);

      if(threadExitedEvent)
         CloseHandle(threadExitedEvent);
      
      threadExitedEvent = INVALID_HANDLE_VALUE;

      WaitForSingleObject(threadHandle, 3000);
      threadHandle = INVALID_HANDLE_VALUE;      
   }

   return 0;
}

/* ******************************************************************* */
int NMAS_RegisterIdentityPlugin(LPFN_NMAS_SetLoginIdentity setIdentity, 
                        LPFN_NMAS_StartIdentityPlugin *startIdentityPlugin,
                        LPFN_NMAS_StopIdentityPlugin *stopIdentityPlugin)
{
   NMAS_SetLoginIdentity = setIdentity;
   *startIdentityPlugin = StartIdentityPlugin;
   *stopIdentityPlugin = StopIdentityPlugin;

   return 0;
}