//Sample code file: var/ndk/webBuildengine/tmp/viewable_samples/a4ad0b48-dd95-46b6-8289-721e99c8dc76/login_method/lcm/win32/guiwin32.cpp

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

//
// Method Name:      Clear Password Method
// Method Platform:   Windows Client
//
// Copyright (C) 2002 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. 
//
//guiwin32.cpp : Defines the initialization routines for the DLL.
//


//win32 includes
class='cKeyword'>#include "stdafx.h"
class='cKeyword'>#include "guiwin32.h"
class='cKeyword'>#include "UserInputDialog.h"

//stdlib includes
class='cKeyword'>#include <stdlib.h>
class='cKeyword'>#include <stdio.h>
class='cKeyword'>#include <memory.h>
class='cKeyword'>#include <string.h>
class='cKeyword'>#include <ntypes.h>
class='cKeyword'>#include <defines.h>
class='cKeyword'>#include <unicode.h>

class='cKeyword'>class='cKeyword'>#ifdef _DEBUG
class='cKeyword'>#define new DEBUG_NEW
class='cKeyword'>#undef THIS_FILE
static class='cKeyword'>char THIS_FILE[] = __FILE__;
class='cKeyword'>#endif


//   Note!
//
//      If this DLL is dynamically linked against the MFC
//      DLLs, any functions exported from this DLL which
//      call into MFC must have the AFX_MANAGE_STATE macro
//      added at the very beginning of the function.
//
//      For example:
//
//      extern "C" BOOL PASCAL EXPORT ExportedFunction()
//      {
//         AFX_MANAGE_STATE(AfxGetStaticModuleState());
//         // normal function body here
//      }
//
//      It is very important that this macro appear in each
//      function, prior to any calls into MFC.  This means that
//      it must appear as the first statement within the 
//      function, even before any object variable declarations
//      as their constructors may generate calls into the MFC
//      DLL.
//
//      Please see MFC Technical Notes 33 and 58 for additional
//      details.
//

/////////////////////////////////////////////////////////////////////////////
// CGuiwin32App

BEGIN_MESSAGE_MAP(CGuiwin32App, CWinApp)
   //{{AFX_MSG_MAP(CGuiwin32App)
      // NOTE - the ClassWizard will add and remove mapping macros here.
      //    DO NOT EDIT what you see in these blocks of generated code!
   //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CGuiwin32App construction

CGuiwin32App::CGuiwin32App()
{
   // TODO: add construction code here,
   // Place all significant initialization in InitInstance
   m_processCount = 0;
}

/////////////////////////////////////////////////////////////////////////////
// The one and only CGuiwin32App object

CGuiwin32App guiwin32App;

BOOL CGuiwin32App::InitInstance()
{
   BOOL rVal = CWinApp::InitInstance();
   return rVal;
}

BOOL WINAPI CGuiwin32App::DllMain( HINSTANCE hinstDLL, DWORD dwReason, LPVOID howLoaded )
{
   AFX_MANAGE_STATE(AfxGetStaticModuleState());
      
   if (dwReason == DLL_PROCESS_ATTACH )
   {
      m_processCount++;
   }
   else if ( dwReason == DLL_PROCESS_DETACH )
   {
      if ( m_processCount > 0 )
         m_processCount--;
   }

   return TRUE;      
}

/**
   SetupLCMDLL
**/

int CGuiwin32App::SetupLCMDLL()
{
   ourProcessID = (long) GetCurrentProcessId();

   return 0;
}

/**
   TakeDownLCMDLL
**/

int CGuiwin32App::TakeDownLCMDLL()
{
   return 0;
}

/* ******************************************************************* */
int getUserInput( int flags, CString **pwd, int *changePwd, CString **newPwd )
{
   AFX_MANAGE_STATE(AfxGetStaticModuleState());
   
   UserInputDialog* dlg;
   dlg = new UserInputDialog( flags & PASSWORD_CHANGE );
   if ( dlg->DoModal() == IDOK ) {
      *pwd       = new CString(dlg->m_UserInput);
      *changePwd = (dlg->m_ChangePassword == TRUE);
      *newPwd    = new CString(dlg->m_newPwd);
      delete dlg;
      return IDOK;
   } else {
      *changePwd = 0;
      delete dlg;
      return IDCANCEL;
   }
}

void showPwdChanged()
{
   AFX_MANAGE_STATE(AfxGetStaticModuleState());
   CString title,msg;
   title.LoadString(IDS_PWD_CHANGED_TITLE);
   msg.LoadString(IDS_PWD_CHANGED);
   MessageBox( NULL, msg, title, MB_OK );
}

void showChangePasswordFailed()
{
   AFX_MANAGE_STATE(AfxGetStaticModuleState());
   CString title,msg;
   title.LoadString(IDS_PWD_CHANGED_TITLE);
   msg.LoadString(IDS_PWD_CHANGED_TITLE);
   MessageBox( NULL, msg, title, MB_OK );
}

/* ******************************************************************* */
/**
   DLL Export Entry function
   Entry point that NMAS will load
**/
/* ******************************************************************* */
int LCM00000001( MAF_Handle mh ) {
   nint32      err = 0, mafErr =0;
   CPWD_INFO   pwdInfo;
   unicode      puPassword[MAX_CLEAR_PWD_CHARS] = {0};
   size_t      passwordLen = 0;
   CString      *userIn = NULL, *newPwd = NULL;
   int         changePwd=0;
   class='cKeyword'>char      pwd[128];
   size_t      replyLen;
   long      ourProcessID = GetCurrentProcessId();

   // start NMAS
   mafErr = MAF_Begin (mh);
   if (mafErr)
   {   
      // very bad error if this fails just error out
      return mafErr;
   }
   
   /*  Retrieve the password from the context */
   passwordLen=sizeof(puPassword);
   if (MAF_GetAttribute(mh, NMAS_AID_PASSWORD, NULL, &passwordLen, puPassword) == 0
      && passwordLen > sizeof(unicode)) // only null terminator returned
   {
      // Remove password so following methods don't try and use it
      MAF_PutAttribute(mh, NMAS_AID_PASSWORD, NULL, 0, NULL);

      // Copy password into userIn unicode to local conversion performed during assignment
      userIn = new CString((LPCWSTR)puPassword);
   }
   else // Need to prompt user for password
   {
      if ( getUserInput( 0, &userIn, &changePwd, &newPwd ) != IDOK )
      {
         err = NMAS_E_LOGIN_CANCELED;
         goto REPORT_ERROR;
      }
   }
   
   // check that the password is not too big for static buffer
   passwordLen = userIn->GetLength();
   
   if (passwordLen < sizeof(pwd))
   {
      strcpy(pwd, LPCTSTR(*userIn));
      pwd[passwordLen] = (class='cKeyword'>char)NULL;
   }
   else
   {
      err = NMAS_E_BUFFER_OVERFLOW;
      goto REPORT_ERROR;
   }

   // set password information
   pwdInfo.error = 0;
   pwdInfo.infoFlags = 0;

   if (changePwd)
   {
      pwdInfo.infoFlags |= PASSWORD_CHANGE;
   }

   // send password information
   mafErr = MAF_Write(mh, sizeof(pwdInfo), &pwdInfo);
   if (mafErr)
   {
      goto MAF_ERROR;
   }

   // send password over MAF encrypted transport
   mafErr = MAF_XWrite(mh, passwordLen, pwd); // Do not include null
      memset(pwd, 0xCC, sizeof(pwd));  // over-write password
   if (mafErr)
   {
      goto MAF_ERROR;
   }

   mafErr = MAF_Read(mh, &replyLen, &err);
   if (mafErr || replyLen < 4 || err)
   {
      goto MAF_ERROR;
   }

   if (changePwd)
   {
      passwordLen = newPwd->GetLength();
      if (passwordLen < sizeof(pwd))
      {
         strcpy(pwd, LPCTSTR(*newPwd));
         pwd[passwordLen] = (class='cKeyword'>char)NULL;
      }
      else
      {
         err = NMAS_E_BUFFER_OVERFLOW;
         goto REPORT_ERROR;
      }

      mafErr = MAF_XWrite( mh, passwordLen, pwd);
       memset(pwd, 0xCC, sizeof(pwd));  // over-write password
        
      if (mafErr)
      {
         goto MAF_ERROR;
      }

      mafErr = MAF_Read( mh, &replyLen, &err);
      if (!mafErr && replyLen >= 4 && !err)
      {   
         //password is changed, display message to user.
         showPwdChanged();
      }
      else
      {
         //unable to change password
         showChangePasswordFailed();
      }
   }

REPORT_ERROR:
   if (err)
   {
      MAF_Write(mh, 4, &err);
   }

MAF_ERROR:

   if (!err)
   {
      err = mafErr;
   }

   if (userIn != NULL)
   {
      delete userIn;
   }

   if (newPwd != NULL)
   {
      delete newPwd;
   }

   // close the session
   MAF_End (mh, err, 0, 0);

   // return only fatal MAF errors
   return mafErr;
}