#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <initguid.h>
#include <windowsx.h>
#include <winuserp.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <lm.h>

#include <shlobj.h>
#include <Cmnquery.h>
#include <dsclient.h>
#include <Dsquery.h>

#include <reason.h>
#include "resource.h"

//#define SNAPSHOT_TEST
#ifdef SNAPSHOT_TEST
#define TESTMSG(x) \
	WriteToConsole((x))
#else
#define TESTMSG(x)
#endif //SNAPSHOT_TEST
//
//	Default warning state for warning user check button
//
#define		DEFAULTWARNINGSTATE BST_CHECKED

#define		TITLEWARNINGLEN 32

//
//	Name of the executable
//
LPWSTR		g_lpszProgramName = NULL;

//
//	Enum for all of the actions.
//
enum 
{
	ACTION_SHUTDOWN = 0,
	ACTION_RESTART = 1,
	ACTION_LOGOFF,
	ACTION_STANDBY,
	ACTION_DISCONNECT,
	ACTION_ABORT
};

//
//	Resource IDs for actions.
//
DWORD g_dwActions[] = 
{
	IDS_ACTION_SHUTDOWN,
	IDS_ACTION_RESTART,
	IDS_ACTION_LOGOFF
	//IDS_ACTION_STANDBY,
	//IDS_ACTION_DISCONNECT,
	//IDS_ACTION_ABORT
};

//
//	Number of actions and the action strings loaded from resource.
//
const int	g_nActions = sizeof(g_dwActions) / sizeof(DWORD);
WCHAR		g_lppszActions[g_nActions][MAX_PATH];

LPWSTR		g_lpszNewComputers = NULL;
WCHAR		g_lpszDefaultDomain[MAX_PATH] = L"";
WCHAR		g_lpszLocalComputerName[MAX_PATH] = L"";
WCHAR		g_lpszTitleWarning[TITLEWARNINGLEN];
BOOL		g_bAssumeShutdown = FALSE;

struct _PROVIDER{
	LPWSTR	szName;
	DWORD	dwLen;
};

typedef struct _SHUTDOWNREASON
{
	DWORD dwCode;
	WCHAR lpName[MAX_REASON_NAME_LEN + 1];
	WCHAR lpDesc[MAX_REASON_DESC_LEN + 1];
} SHUTDOWNREASON, *PSHUTDOWNREASON;

PSHUTDOWNREASON g_lpReasons = NULL;
DWORD		g_dwReasons = 0;
DWORD		g_dwReasonSelect;
DWORD		g_dwActionSelect;

typedef struct _SHUTDOWNCACHEDHWNDS
{
	HWND hwndShutdownDialog;
	HWND hwndListSelectComputers;
	HWND hwndEditComment;
	HWND hwndStaticDesc;
	HWND hwndEditTimeout;
	HWND hwndButtonWarning;
	HWND hwndComboAction;
	HWND hwndComboOption;
	HWND hwndBtnAdd;
	HWND hwndBtnRemove;
	HWND hwndBtnBrowse;
	HWND hwndChkPlanned;
	HWND hwndButtonOK;
} SHUTDOWNCACHEDHWNDS, *PSHUTDOWNCACHEDHWNDS;

SHUTDOWNCACHEDHWNDS g_wins;

HMODULE		g_hDllInstance = NULL;
typedef		BOOL (*REASONBUILDPROC)(REASONDATA *, BOOL, BOOL);
typedef		VOID (*REASONDESTROYPROC)(REASONDATA *);

BOOL		GetNetworkComputers(HWND hwndList, HWND hwndProgress, LPCWSTR lpDomain);
BOOL		GetComputerNameFromPath(LPWSTR szPath, LPWSTR szName);
VOID		AdjustWindowState();
INT_PTR 
CALLBACK	Shutdown_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam,
                                     LPARAM lParam);
INT_PTR 
CALLBACK	AddNew_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam,
                                     LPARAM lParam);
INT_PTR 
CALLBACK	Browse_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam,
                                     LPARAM lParam);
BOOL		Shutdown_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify);
BOOL		AddNew_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify);
BOOL		Browse_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify);
BOOL		Shutdown_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam);
BOOL		Browse_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam);

typedef         void (*PSetThreadUILanguage)(DWORD);


//
//	Check whether a string is all white spaces.
//
BOOL 
IsEmpty(LPCWSTR lpCWSTR)
{
	if(!lpCWSTR)
		return TRUE;
	while(*lpCWSTR && (*lpCWSTR == '\n' || *lpCWSTR == '\t' || *lpCWSTR == '\r' || *lpCWSTR == ' '))
		lpCWSTR++;
	if(*lpCWSTR)
		return FALSE;
	return TRUE;
}

// Write the string to console
VOID
WriteToConsole(
    LPWSTR  pszMsg
    )
{
	HANDLE	hConsole = GetStdHandle( STD_OUTPUT_HANDLE );

    if ( !pszMsg || !*pszMsg )
        return;

    DWORD   dwStrLen        = lstrlenW( pszMsg );
    LPSTR   pszAMsg         = NULL;
    DWORD   dwBytesWritten  = 0;
    DWORD   dwMode          = 0;

    if ( (GetFileType ( hConsole ) & FILE_TYPE_CHAR ) && 
         GetConsoleMode( hConsole, &dwMode ) )
    {
         WriteConsoleW( hConsole, pszMsg, dwStrLen, &dwBytesWritten, 0 );
         return;
    } 	
    
    // console redirect to a file.
    if ( !(pszAMsg = (LPSTR)LocalAlloc(LMEM_FIXED, (dwStrLen + 1) * sizeof(WCHAR) ) ) )
    {
        return;
    }

    if (WideCharToMultiByte(GetConsoleOutputCP(),
                                    0,
                                    pszMsg,
                                    -1,
                                    pszAMsg,
                                    dwStrLen * sizeof(WCHAR),
                                    NULL,
                                    NULL) != 0 
									&& hConsole)
    {
        WriteFile(  hConsole,
                        pszAMsg,
                        lstrlenA(pszAMsg),
                        &dwBytesWritten,
                        NULL );
    
    }
    
    LocalFree( pszAMsg );
}


// Report error.
VOID
report_error(
    DWORD error_code
    )
{
    LPVOID msgBuf = 0;
    FormatMessageW(
        FORMAT_MESSAGE_ALLOCATE_BUFFER | 
        FORMAT_MESSAGE_FROM_SYSTEM | 
        FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
        error_code,
        MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language
        reinterpret_cast< wchar_t* >( &msgBuf ),
        0,
        NULL);

    //fwprintf( stderr, L"%s : %s\n", g_lpszProgramName, reinterpret_cast< wchar_t* >( msgBuf ));
    WriteToConsole( reinterpret_cast<wchar_t*> (msgBuf) ); 
	    
    LocalFree( msgBuf );
}


BOOL
parse_reason_code(
    LPCWSTR  arg,
    LPDWORD  lpdwReason
    )
{
    // Code consists of flags:major:minor
    int major = 0;
    int minor = 0;

    const int state_start = 0;
    const int state_flags = 0;
    const int state_major = 1;
    const int state_minor = 2;
    const int state_null = 3;
    const int state_done = 4;

    for( int i = 0, state = state_start; state != state_done; ++i )
    {
        switch( state )
        {
        case state_flags :
            // Expecting flags
            switch( arg[ i ] ) {
            case L'U' : case L'u' :
                *lpdwReason |= 0x40000000; // SHTDN_REASON_FLAG_USER_DEFINED
                break;
            case L'P' : case L'p' :
                *lpdwReason |= 0x80000000; // SHTDN_REASON_FLAG_PLANNED
                break;
            case L':' :
                state = state_major;
                break;
            case 0 : 
                // End of string (use default major and minor).
                state = state_done;
                break;
            default :
                return FALSE;
            }
            break;
        case state_major :
            // Expecting major
            if( arg[ i ] >= L'0' && arg[ i ] <= L'9' ) {
                major = major * 10 + arg[ i ] - L'0';
            }
            else {
                // Make sure we only have 8 bits
                if( major > 0xff ) return FALSE;
                *lpdwReason |= major << 16;
                if( arg[ i ] == 0 ) {
                    // use default minor reason.
                    state = state_done;
                }
                if( arg[ i ] == L':' ) {
                    state = state_minor;
                }
                else return FALSE;
            }
            break;
        case state_minor :
            // Expecting minor reason
            // Expecting major
            if( arg[ i ] >= L'0' && arg[ i ] <= L'9' ) {
                minor = minor * 10 + arg[ i ] - L'0';
            }
            else {
                // Make sure we only have 8 bits
                if( minor > 0xffff ) return FALSE;
                *lpdwReason = ( *lpdwReason & 0xffff0000 ) | minor;
                if( arg[ i ] == 0 ) {
                    return state_done;
                }
                if( arg[ i ] == L':' ) {
                    state = state_null;
                }
                else return FALSE;
            }
            break;
        case state_null :
            // Expecting end of string
            if( arg[ i ] != 0 ) return FALSE;
            state = state_done;
        default :
            return FALSE;
        }
    }
    return TRUE;
}


// Parses an integer if it is in decimal notation.
// Returns FALSE if it is malformed.
BOOL
parse_int(
    const wchar_t* arg,
    LPDWORD lpdwInt
    )
{
    *lpdwInt = 0;
    while( *arg ) {
        if( *arg >= L'0' && *arg <= L'9' ) {
            *lpdwInt = *lpdwInt * 10 + int( *arg++ - L'0' );
        }
        else {
            return FALSE;
        }
    }
    return TRUE;
}

// Parse options.
// Returns FALSE if the option strings are malformed.  This causes the usage to be printed.
BOOL
parse_options(
    int      argc,
    wchar_t  *argv[],
    LPBOOL   lpfLogoff,
    LPBOOL   lpfForce,
    LPBOOL   lpfReboot,
    LPBOOL   lpfAbort,
    LPWSTR   *ppServerName,
    LPWSTR   *ppMessage,
    LPDWORD  lpdwTimeout,
    LPDWORD  lpdwReason
    )
{
    BOOL  fShutdown = FALSE;

    *lpfLogoff    = FALSE;
    *lpfForce     = FALSE;
    *lpfReboot    = FALSE;
    *lpfAbort     = FALSE;
    *ppServerName = NULL;
    *ppMessage    = NULL;
    *lpdwTimeout  = 30;
    *lpdwReason   = 0xFF;

	//
	//	Set default reason to be planned
	//
	*lpdwReason |= 0x80000000; // SHTDN_REASON_FLAG_PLANNED

    for( int i = 1; i < argc; ++i )
    {
        wchar_t* arg = argv[ i ];

        switch( arg[ 0 ] )
        {
            case L'/' : case L'-' :

                switch( arg[ 1 ] )
                {
                    case L'L' : case L'l' :

                        *lpfLogoff = TRUE;
                        if (arg[2] != 0) return FALSE;
                        break;

                    case L'S' : case L's' :

                        //
                        // Use server name if supplied  (i.e. do nothing here)
                        //

                        fShutdown = TRUE;
                        if( arg[ 2 ] != 0 ) return FALSE;
                        break;

                    case L'F' : case L'f' :

                        *lpfForce = TRUE;
                        if( arg[ 2 ] != 0 ) return FALSE;
                        break;

                    case L'R' : case L'r' :

                        *lpfReboot = TRUE;
                        if( arg[ 2 ] != 0 ) return FALSE;
                        break;

                    case L'A' : case L'a' :

                        *lpfAbort = TRUE;
                        if( arg[ 2 ] != 0 ) return FALSE;
                        break;

                    case L'T' : case L't' :

                        //
                        // Next arg should be number of seconds
                        //

                        if (++i == argc)
                        {
                            return FALSE;
                        }

                        arg = argv[i];

                        if( arg[ 0 ] < L'0' || arg[ 0 ] > L'9' ) return FALSE;
                        if( !parse_int( arg, lpdwTimeout )) return FALSE;
                        break;

                    case L'Y' : case L'y' :

                        // Ignore this option.
                        break;

                    case L'D' : case L'd' :

                        //
                        // Next arg should be reason code
                        //

                        if (++i == argc)
                        {
                            return FALSE;
                        }

                        arg = argv[i];
						
						//
						//If reason code is given, we clear the planned bit.
						//
						*lpdwReason &= ~(0x80000000); // SHTDN_REASON_FLAG_PLANNED

                        if( !parse_reason_code( arg, lpdwReason ))
                        {
                            return FALSE;
                        }

                        break;

                    case L'C' : case L'c' :

                        //
                        // Next arg should be shutdown message.  Make
                        // sure only one is specified.
                        //

                        if (++i == argc || *ppMessage)
                        {
                            return FALSE;
                        }

                        arg = argv[i];

                        *ppMessage = arg;

                        break;

                    case L'M' : case L'm' :

                        //
                        // Next arg should be machine name.  Make
                        // sure only one is specified.
                        //

                        if (++i == argc || *ppServerName)
                        {
                            return FALSE;
                        }

                        arg = argv[i];

                        if (arg[0] == L'\\' && arg[1] == L'\\')
                        {
                            *ppServerName = arg + 2;
                        }
                        else
                        {
                            *ppServerName = arg;
                        }

                        break;

                    case L'H' : case L'h' : case L'?' : default : 

                        return FALSE;
                }

                break;

            default :

                //
                // Junk
                //

                return FALSE;
        }
    }


    //
    // Default is to logoff
    //

    if (!fShutdown && !*lpfReboot && !*lpfAbort)
    {
        *lpfLogoff = TRUE;
    }


    //
    // Check for mutually exclusive options
    //

    if (*lpfAbort && (*lpfLogoff || fShutdown || *lpfReboot || *lpfForce))
    {
        return FALSE;
    }

    if (*lpfLogoff && (*ppServerName || fShutdown || *lpfReboot))
    {
        return FALSE;
    }

    if (fShutdown && *lpfReboot)
    {
        return FALSE;
    }

    return TRUE;
}


// Print out usage help string.
VOID
usage(
    VOID
    )
{
    HMODULE  	hModule = GetModuleHandle( NULL );
    int 	buf_len = MAX_PATH;
    int 	new_len	= 0;
    LPWSTR 	buf	    = NULL;
    LPWSTR 	msg	    = NULL;

    if( hModule == NULL )
    {
        report_error( GetLastError() );
        return;
    }

    buf = (LPWSTR) LocalAlloc(LMEM_FIXED, buf_len * sizeof(WCHAR));

    if (buf == NULL)
    {
        report_error( GetLastError() );
        return;
    }

    new_len = LoadStringW( hModule, IDS_USAGE, buf, buf_len );

    //
    // Since LoadString doesn't tell you how much data you should have
    // if the buffer's too small, retry until we succeed.
    //

    while( new_len + 1 == buf_len )
    {
        LocalFree(buf);
        buf_len *= 2;
        buf = (LPWSTR) LocalAlloc(LMEM_FIXED, buf_len * sizeof(WCHAR));

        if (buf == NULL)
        {
            report_error( GetLastError() );
            return;
        }

        new_len = LoadStringW( hModule, IDS_USAGE, buf, buf_len );
    }

    if( 0 == new_len )
    {
        report_error( GetLastError() );
        LocalFree(buf);
        return;
    }
        
    //fwprintf( stderr, buf, g_lpszProgramName );
    new_len = lstrlenW( buf ) + lstrlenW( g_lpszProgramName ) + 1;	

    if ( msg = (LPWSTR)LocalAlloc(LMEM_FIXED, new_len * sizeof(WCHAR) ) )
    {
	    swprintf(msg, buf, g_lpszProgramName );
	    WriteToConsole( msg );
    }
    else
    {
	    report_error( GetLastError() );
    }

    LocalFree(buf);
    LocalFree(msg);
}


// We need shutdown privileges enabled to be able to shut down our machines.
BOOL
enable_privileges(
    LPCWSTR  lpServerName,
    BOOL     fLogoff 
    )
{
    NTSTATUS	Status = STATUS_SUCCESS;
	NTSTATUS	Status1 = STATUS_SUCCESS;
    BOOLEAN		fWasEnabled;

    if (fLogoff)
    {
        //
        // No privileges to get
        //

        return TRUE;
    }

	//
	//	We will always enable both privileges so 
	//	it can work for telnet sessions.
	//
	Status = RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE,
									TRUE,
									FALSE,
									&fWasEnabled);

	Status1 = RtlAdjustPrivilege(SE_REMOTE_SHUTDOWN_PRIVILEGE,
									TRUE,
									FALSE,
									&fWasEnabled);

    if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status1))
    {
		report_error(RtlNtStatusToDosError(Status));
		report_error(RtlNtStatusToDosError(Status1));
		return FALSE;
    }

    return TRUE;
}


VOID __cdecl
wmain(
    int      argc,
    wchar_t *argv[]
    )
{
    BOOL    fLogoff;
    BOOL    fForce;
    BOOL    fReboot;
    BOOL    fAbort;
    LPWSTR  lpServerName;
    LPWSTR  lpMessage;
    DWORD   dwTimeout;
    DWORD   dwReason;
	INT_PTR hResult;

	HINSTANCE hInstance = LoadLibrary( L"kernel32.dll" );
    if ( hInstance )
    {
        PSetThreadUILanguage SetThreadUILang = (PSetThreadUILanguage)GetProcAddress( hInstance, "SetThreadUILanguage" );
        
        if ( SetThreadUILang )
             (*SetThreadUILang)( 0 );

        FreeLibrary( hInstance );
    }

    // We use the program name for reporting errors.
    g_lpszProgramName = argv[ 0 ];

	//
	//	Userdomain is used as the default domain.
	//
	GetEnvironmentVariableW(L"USERDOMAIN", g_lpszDefaultDomain, MAX_PATH);
	GetEnvironmentVariableW(L"COMPUTERNAME", g_lpszLocalComputerName, MAX_PATH);

	//
	//	if there is no arguments, we will display help.
	//
	if(argc == 1)
	{
		usage();
        return;
	}

	//
	//	If the first argument is -i or /i, we pop up UI.
	//
	if(wcsncmp(argv[1], L"-i", 2) == 0 || wcsncmp(argv[1], L"/i", 2) == 0
		|| wcsncmp(argv[1], L"-I", 2) == 0 || wcsncmp(argv[1], L"/I", 2) == 0)
	{
		g_hDllInstance = GetModuleHandle(NULL);
		if(g_hDllInstance)
		{
			hResult = DialogBoxParam(g_hDllInstance, MAKEINTRESOURCE(IDD_DIALOGSHUTDOWN), NULL, Shutdown_DialogProc, NULL);
			
			if(g_lpReasons)
				LocalFree((HLOCAL)g_lpReasons);
		}
		return;
	}
    // Parse the options.
    if( !parse_options( argc,
                        argv,
                        &fLogoff,
                        &fForce,
                        &fReboot,
                        &fAbort,
                        &lpServerName,
                        &lpMessage,
                        &dwTimeout,
                        &dwReason ))
    {
        usage();
        return;
    }

    // Get all privileges so that we can shutdown the machine.
    if( !enable_privileges( lpServerName, fLogoff ))
    {
		TESTMSG(L"enable_privileges failed\n");
        return;
    }

    // Do the work.
    if( fAbort )
    {
        if( !AbortSystemShutdownW( lpServerName ))
        {
            report_error( GetLastError( ));
        }
    }
    else if (fLogoff)
    {
        if (!ExitWindowsEx(fForce ? EWX_LOGOFF : (EWX_LOGOFF | EWX_FORCE),
                           0))
        {
            report_error(GetLastError());
        }
    }
    else
    {
        // Do the normal form.
        if( !InitiateSystemShutdownExW( lpServerName,
                                        lpMessage,
                                        dwTimeout,
                                        fForce,
                                        fReboot,
                                        dwReason ))
        {
			TESTMSG(L"InitiateSystemShutdownExW failed\n");
            report_error( GetLastError( ));
        }
    }
}


//
//	Get the computers in the spesified domain and populate the list box
//
BOOL GetNetworkComputers(HWND hwndList, HWND hwndProgress, LPCWSTR lpDomain)
{
	LPSERVER_INFO_101	pBuf = NULL;
	LPSERVER_INFO_101	pTmpBuf;
	DWORD				dwLevel = 101;
	DWORD				dwPrefMaxLen = -1;
	DWORD				dwEntriesRead = 0;
	DWORD				dwTotalEntries = 0;
	DWORD				dwTotalCount = 0;
	DWORD				dwServerType = SV_TYPE_SERVER; // all servers
	DWORD				dwResumeHandle = 0;
	NET_API_STATUS		nStatus;
	LPWSTR				pszServerName = NULL;
	WCHAR				lpWSTR[MAX_PATH];
	DWORD				i;
	WCHAR				er[MAX_PATH];
	WCHAR				wsz[MAX_PATH];


	LoadStringW(g_hDllInstance, IDS_GETCOMPUTERNAMEWAIT, er, MAX_PATH);
	LoadStringW(g_hDllInstance, IDS_GETCOMPUTERNAMEPROGRESS, wsz, MAX_PATH);

	SetWindowTextW(hwndProgress, er);
	nStatus = NetServerEnum(NULL,
                           dwLevel,
                           (LPBYTE *) &pBuf,
                           dwPrefMaxLen,
                           &dwEntriesRead,
                           &dwTotalEntries,
                           dwServerType,
                           lpDomain,
                           &dwResumeHandle);
   //
   // If the call succeeds,
   //
   if ((nStatus == NERR_Success) || (nStatus == ERROR_MORE_DATA))
   {
		if ((pTmpBuf = pBuf) != NULL)
		{
			//
			//	Loop through the entries and 
			//  add each computer name to list.
			//
			for (i = 0; i < dwEntriesRead; i++)
			{
				if (pTmpBuf == NULL)
				{
				   break;
				}

				wcscpy(lpWSTR, pTmpBuf->sv101_name);

				if(i+1 > 0 && (i+1) % 500 == 0){
					DWORD percentage = ((i+1)*100)/dwEntriesRead;
					swprintf(er, L"%d%% %s(%d)...", percentage, wsz, i+1);
					SetWindowTextW(hwndProgress, er);
				}

				//
				//	We don't add dups.
				//
				if(LB_ERR == ListBox_FindString(hwndList, -1, lpWSTR))
					ListBox_AddString(hwndList, lpWSTR);

				pTmpBuf++;
				dwTotalCount++;
			}

			//
			//	Display a warning if all available entries were
			//  not enumerated, print the number actually 
			//  enumerated, and the total number available.
			//

			if (nStatus == ERROR_MORE_DATA)
			{
				LoadStringW(g_hDllInstance, IDS_GETCOMPUTERNAMEMOREDATA, er, MAX_PATH);
				SetWindowTextW(hwndProgress, er);
			}

			LoadStringW(g_hDllInstance, IDS_GETCOMPUTERNAMECOMPLETE, wsz, MAX_PATH);
			swprintf(er, L"%s %d)", wsz, dwTotalCount);
			SetWindowTextW(hwndProgress, er);
		}
	}
	else 
	{
		LoadStringW(g_hDllInstance, IDS_GETCOMPUTERNAMEERROR, wsz, MAX_PATH);
		swprintf(er, L"%s: %d", wsz, nStatus);
		SetWindowTextW(hwndProgress, er);
	}
   //
   // Free the allocated buffer.
   //
   if (pBuf != NULL)
      NetApiBufferFree(pBuf);

   return TRUE;
}

//
//	Get computername from ADSI path
//	Here we only handle WinNT, LDAP, NWCOMPAT, and NDS.
//
BOOL GetComputerNameFromPath(LPWSTR szPath, LPWSTR szName)
{
	static _PROVIDER p[] =
	{
		{L"LDAP://", 7},
		{L"WinNT://", 8}, 
		{L"NWCOMPAT://", 11},
		{L"NDS://", 6}
	};

	static UINT np = sizeof(p)/sizeof(_PROVIDER);
	LPWSTR lpsz = NULL;

	if(!szPath || !szName)
		return FALSE;

	for(UINT i = 0; i < np; i++)
	{
		if(wcsncmp(szPath, p[i].szName, p[i].dwLen) == 0)
		{
			switch(i)
			{
			case 0: //	LDAP
				lpsz = wcsstr(szPath, L"CN=");
				if(!lpsz)
					return FALSE;
				lpsz += 3;
				
				while(*lpsz && *lpsz != ',')
					*szName++ = *lpsz++;
				*szName = 0;
				return TRUE;
			case 1: //	WinNT
			case 2: //	NWCOMPAT
				lpsz = szPath + p[i].dwLen;
				//
				//	skip domain or provider path
				//
				while(*lpsz && *lpsz != '/')
					lpsz++;
				lpsz++;

				while(*lpsz && *lpsz != '/')
					*szName++ = *lpsz++;
				*szName = 0;
				return TRUE;
			case 3: //	NDS
				lpsz = wcsstr(szPath, L"CN=");
				if(!lpsz)
					return FALSE;
				lpsz += 3;
				
				while(*lpsz && *lpsz != '/')
					*szName++ = *lpsz++;
				*szName = 0;
				return TRUE;
			default:
				return FALSE;
			}
		}
	}
	return FALSE;
}

//
//	A centralized place for adjusting window states.
//
VOID AdjustWindowState()
{
	if(g_dwActionSelect == ACTION_SHUTDOWN || g_dwActionSelect == ACTION_RESTART)
	{
		EnableWindow(g_wins.hwndButtonWarning, TRUE);
		if (IsDlgButtonChecked(g_wins.hwndShutdownDialog, IDC_CHECKWARNING) == BST_CHECKED)
			EnableWindow(g_wins.hwndEditTimeout, TRUE);
		else
			EnableWindow(g_wins.hwndEditTimeout, FALSE);

		EnableWindow(g_wins.hwndEditComment, TRUE);
		if(g_bAssumeShutdown)
		{
			EnableWindow(g_wins.hwndComboOption, FALSE);
			EnableWindow(g_wins.hwndChkPlanned, FALSE);
			EnableWindow(g_wins.hwndButtonOK, TRUE);
		}
		else
		{
			EnableWindow(g_wins.hwndComboOption, TRUE);
			EnableWindow(g_wins.hwndChkPlanned, TRUE);
			if(g_dwReasonSelect != -1 && (g_lpReasons[g_dwReasonSelect].dwCode & SHTDN_REASON_FLAG_COMMENT_REQUIRED))
			{
				if(Edit_GetTextLength(g_wins.hwndEditComment) > 0)
					EnableWindow(g_wins.hwndButtonOK, TRUE);
				else
					EnableWindow(g_wins.hwndButtonOK, FALSE);
			}
			else
			{
				EnableWindow(g_wins.hwndButtonOK, TRUE);
			}
		}
		EnableWindow(g_wins.hwndBtnAdd, TRUE);
		EnableWindow(g_wins.hwndBtnBrowse, TRUE);
		EnableWindow(g_wins.hwndBtnRemove, TRUE);
		EnableWindow(g_wins.hwndListSelectComputers, TRUE);
	}
	else
	{
		EnableWindow(g_wins.hwndChkPlanned, FALSE);
		EnableWindow(g_wins.hwndButtonWarning, FALSE);
		EnableWindow(g_wins.hwndBtnAdd, FALSE);
		EnableWindow(g_wins.hwndBtnBrowse, FALSE);
		EnableWindow(g_wins.hwndBtnRemove, FALSE);
		EnableWindow(g_wins.hwndComboOption, FALSE);
		EnableWindow(g_wins.hwndEditComment, FALSE);
		EnableWindow(g_wins.hwndEditTimeout, FALSE);
		EnableWindow(g_wins.hwndListSelectComputers, FALSE);
		EnableWindow(g_wins.hwndButtonOK, TRUE);
	}
}

//
//	Init dialog handler for the shutdown dialog.
//
BOOL Shutdown_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
{
	HMODULE				hUser32;
	REASONBUILDPROC		buildProc;
	REASONDESTROYPROC	DestroyProc;
	WCHAR				lpReasonName[MAX_PATH];
	REASONDATA			Reasons;
	int					i;

	//
	//	Init all of the dialog items so we dont have to find
	//	them everytime we need them.
	//
	g_wins.hwndShutdownDialog	= hwnd;
	g_wins.hwndButtonWarning	= GetDlgItem(hwnd, IDC_CHECKWARNING);
	g_wins.hwndComboAction		= GetDlgItem(hwnd, IDC_COMBOACTION);
	g_wins.hwndComboOption		= GetDlgItem(hwnd, IDC_COMBOOPTION);
	g_wins.hwndEditComment		= GetDlgItem(hwnd, IDC_EDITCOMMENT);
	g_wins.hwndStaticDesc		= GetDlgItem(hwnd, IDC_STATICDESCRIPTION);
	g_wins.hwndEditTimeout		= GetDlgItem(hwnd, IDC_EDITTIMEOUT);
	g_wins.hwndListSelectComputers = GetDlgItem(hwnd, IDC_LISTSELECTEDCOMPUTERS);
	g_wins.hwndBtnAdd			= GetDlgItem(hwnd, IDC_BUTTONADDNEW);
	g_wins.hwndBtnBrowse		= GetDlgItem(hwnd, IDC_BUTTONBROWSE);
	g_wins.hwndBtnRemove		= GetDlgItem(hwnd, IDC_BUTTONREMOVE);
	g_wins.hwndChkPlanned		= GetDlgItem(hwnd, IDC_CHECK_PLANNED);
	g_wins.hwndButtonOK			= GetDlgItem(hwnd, IDOK);
	
	if(g_wins.hwndButtonWarning == NULL 
		|| g_wins.hwndComboAction == NULL 
		|| g_wins.hwndComboOption == NULL 
		|| g_wins.hwndEditComment == NULL
		|| g_wins.hwndStaticDesc == NULL
		|| g_wins.hwndEditTimeout == NULL
		|| g_wins.hwndListSelectComputers == NULL
		|| g_wins.hwndBtnAdd == NULL
		|| g_wins.hwndBtnBrowse == NULL
		|| g_wins.hwndBtnRemove == NULL
		|| g_wins.hwndChkPlanned == NULL)
	{
		report_error( GetLastError( ));
		EndDialog(hwnd, (int)-1);
		return FALSE;
	}
	
	LoadString(g_hDllInstance, IDS_DIALOGTITLEWARNING, g_lpszTitleWarning, TITLEWARNINGLEN);

	//
	//	Default timeout is set to 20 seconds.
	//
	Edit_SetText(g_wins.hwndEditTimeout, L"20");
	if(! CheckDlgButton(hwnd, IDC_CHECKWARNING, DEFAULTWARNINGSTATE))
	{
		report_error( GetLastError( ));
		EndDialog(hwnd, (int)-1);
		return FALSE;
	}

	//
	//	The for loop will load all of the actions into action combo.
	//	in the meantime we save them for later use.
	//
	for(i = 0; i < g_nActions; i++)
	{
		LoadString(g_hDllInstance, g_dwActions[i], g_lppszActions[i], MAX_PATH - 1);
		ComboBox_AddString(g_wins.hwndComboAction, g_lppszActions[i]);
		if(g_dwActions[i] == IDS_ACTION_SHUTDOWN)
		{
			ComboBox_SelectString(g_wins.hwndComboAction, -1, g_lppszActions[i]);
			g_dwActionSelect = ACTION_SHUTDOWN;
		}
	}

	hUser32 = LoadLibraryW(L"user32.dll");
	if(hUser32 != NULL)
	{
		//
		//	We are using the user32.dll to get and destroy the reasons.
		//	The reasons are added to the option combo and also cached for later use.
		//
		buildProc = (REASONBUILDPROC)GetProcAddress(hUser32, "BuildReasonArray");
		DestroyProc = (REASONDESTROYPROC)GetProcAddress(hUser32, "DestroyReasons");
		if(!buildProc || !DestroyProc)
		{
			FreeLibrary(hUser32);
			hUser32 = NULL;
			g_bAssumeShutdown = TRUE;
		}
		
	}
	else
	{
		g_bAssumeShutdown = TRUE;
	}

	
	//
	//	If we dont have BuildReasonArray() and DestroyReasons() is user32.dll (pre whistler)
	//	we will disable he option combo box.
	//
	if(!g_bAssumeShutdown)
	{
		if(!(*buildProc)(&Reasons, TRUE, FALSE))
		{
			report_error( GetLastError( ));
			FreeLibrary(hUser32);
			EndDialog(hwnd, (int)-1);
			return FALSE;
		}
		else 
		{
			int		iOption;
			int		iFirst = -1;
			DWORD	dwCheckState = 0x0;
		
			//
			//	Alloc space for reasons.
			//
			g_lpReasons = (PSHUTDOWNREASON)LocalAlloc(LMEM_FIXED, Reasons.cReasons * sizeof(SHUTDOWNREASON));
			if(!g_lpReasons)
			{
				report_error( GetLastError( ));
				FreeLibrary(hUser32);
				EndDialog(hwnd, (int)-1);
				return FALSE;
			}

			//
			//	Set the default to be planned.
			//
			CheckDlgButton(hwnd, IDC_CHECK_PLANNED, BST_CHECKED);
			if (IsDlgButtonChecked(hwnd, IDC_CHECK_PLANNED) == BST_CHECKED)
				dwCheckState = SHTDN_REASON_FLAG_PLANNED;

			//
			//	Init this guy number of reasons.
			//
			g_dwReasons = Reasons.cReasons;

			//
			//	Now populate the combo according the current check state.
			//
			for (iOption = 0; iOption < (int)Reasons.cReasons; iOption++)
			{
				wcscpy(g_lpReasons[iOption].lpName, Reasons.rgReasons[iOption]->szName);
				wcscpy(g_lpReasons[iOption].lpDesc, Reasons.rgReasons[iOption]->szDesc);
				g_lpReasons[iOption].dwCode = Reasons.rgReasons[iOption]->dwCode;
				if(((Reasons.rgReasons[iOption]->dwCode) & SHTDN_REASON_FLAG_PLANNED) == dwCheckState)
				{
					if(iFirst == -1)
						iFirst = iOption;
					ComboBox_AddString(g_wins.hwndComboOption, g_lpReasons[iOption].lpName);
				}
			}

			//
			//	do a default selection (the first one), and set the description.
			//
			g_dwReasonSelect = iFirst;
			if(g_dwReasons > 0 && iFirst != -1)
			{
				ComboBox_SelectString(g_wins.hwndComboOption, -1, g_lpReasons[iFirst].lpName);
				SetWindowTextW(g_wins.hwndStaticDesc,  g_lpReasons[iFirst].lpDesc);
			}
			else
			{
				return FALSE;
			}

			//
			// Setup the comment box.
			// We must fix the maximum characters.
			//
			SendMessage( g_wins.hwndEditComment, EM_LIMITTEXT, (WPARAM)MAX_REASON_COMMENT_LEN, (LPARAM)0 );
			
			(*DestroyProc)(&Reasons);
			FreeLibrary(hUser32);
		}
	}

	AdjustWindowState();

	return TRUE;
}

//
//	Init dialog handler for browse dialog
//
BOOL Browse_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
{
	HWND	hwndDomain = NULL;
	int		cItems = 1024;
	int		lpItems[1024];
	int		cActualItems;
	WCHAR	lpDomain[MAX_PATH];

	hwndDomain = GetDlgItem(hwnd, IDC_EDITDOMAIN);

	if(!hwndDomain)
		return FALSE;

	Edit_SetText(hwndDomain, g_lpszDefaultDomain);;

	return TRUE;
}

//
//	winproc for shutdown dialog
//
INT_PTR CALLBACK Shutdown_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam,
                                  LPARAM lParam)
{
    switch (uMsg)
    {
        HANDLE_MSG(hwnd, WM_INITDIALOG, Shutdown_OnInitDialog);
        HANDLE_MSG(hwnd, WM_COMMAND, Shutdown_OnCommand);
	case (WM_SYSCOMMAND): 
		return (Shutdown_OnCommand(hwnd, (int)(LOWORD(wParam)), (HWND)(lParam), (UINT)HIWORD(wParam)), 0L);
    }

    return FALSE;
}

//
//	winproc for Browse dialog
//
INT_PTR CALLBACK Browse_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam,
                                  LPARAM lParam)
{
    switch (uMsg)
    {
        HANDLE_MSG(hwnd, WM_INITDIALOG, Browse_OnInitDialog);
        HANDLE_MSG(hwnd, WM_COMMAND, Browse_OnCommand);
    }

    return FALSE;
}

//
//	winproc for AddNew dialog
//
INT_PTR CALLBACK AddNew_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam,
                                  LPARAM lParam)
{
    switch (uMsg)
    {
        HANDLE_MSG(hwnd, WM_COMMAND, AddNew_OnCommand);
    }

    return FALSE;
}

//
//	Command handler for the shutdown dialog.
//
BOOL Shutdown_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
{
    BOOL		fHandled = FALSE;
    DWORD		dwDlgResult = 0;
	HINSTANCE	h;

    switch (id)
    {
    case IDCANCEL:
        if (codeNotify == BN_CLICKED)
        {  
			EndDialog(hwnd, (int) dwDlgResult);
        }
	fHandled = TRUE;
        break;
	case SC_CLOSE:
		EndDialog(hwnd, (int) dwDlgResult);
		fHandled = TRUE;
		break;
	case IDC_BUTTONREMOVE:
        if (codeNotify == BN_CLICKED)
        {  
			  int	cItems = 1024;
			  int	lpItems[1024];
			  int	cActualItems;
			  WCHAR	lpServerName[MAX_PATH];

			  //
			  //	Get the number of selected items. If there is any remove them one by one.
			  //
			  cActualItems = ListBox_GetSelItems(g_wins.hwndListSelectComputers, cItems, lpItems);
			  if(cActualItems > 0)
			  {
				  int i;
				  for(i = cActualItems-1; i >= 0; i--)
				  {
					  ListBox_DeleteString(g_wins.hwndListSelectComputers, lpItems[i]);
				  }
			  }
			  fHandled = TRUE;
		}
        break;
	case IDC_CHECK_PLANNED:
		if (codeNotify == BN_CLICKED)
        { 
			int		iOption;
			int		iFirst = -1;
			DWORD	dwCheckState = 0x0;

			//
			//	Get check button state.
			//
			if (IsDlgButtonChecked(hwnd, IDC_CHECK_PLANNED) == BST_CHECKED)
				dwCheckState = SHTDN_REASON_FLAG_PLANNED;

			//
			//	Remove all items from combo
			//
			while (ComboBox_GetCount(g_wins.hwndComboOption))
				ComboBox_DeleteString(g_wins.hwndComboOption, 0);

			//
			//	Now populate the combo according the current check state.
			//
			for (iOption = 0; iOption < (int)g_dwReasons; iOption++)
			{
				if(((g_lpReasons[iOption].dwCode) & SHTDN_REASON_FLAG_PLANNED) == dwCheckState)
				{
					ComboBox_AddString(g_wins.hwndComboOption, g_lpReasons[iOption].lpName);
					if(iFirst == -1)
						iFirst = iOption;
				}
			}

			//
			//	do a default selection (the first one), and set the description.
			//
			if(iFirst != -1)
			{
				ComboBox_SelectString(g_wins.hwndComboOption, -1, g_lpReasons[iFirst].lpName);
				SetWindowTextW(g_wins.hwndStaticDesc,  g_lpReasons[iFirst].lpDesc);
			}
			g_dwReasonSelect = iFirst;
			AdjustWindowState();
			fHandled = TRUE;
		}
		break;
	case IDC_EDITCOMMENT:
        if( codeNotify == EN_CHANGE) 
        {
			if(g_dwReasonSelect != -1 && (g_lpReasons[g_dwReasonSelect].dwCode & SHTDN_REASON_FLAG_COMMENT_REQUIRED))
			{
				if(Edit_GetTextLength(g_wins.hwndEditComment) > 0)
					EnableWindow(g_wins.hwndButtonOK, TRUE);
				else
					EnableWindow(g_wins.hwndButtonOK, FALSE);
			}
			else
			{
				EnableWindow(g_wins.hwndButtonOK, TRUE);
			}
            fHandled = TRUE;
        }
        break;

	case IDC_BUTTONADDNEW:
        if (codeNotify == BN_CLICKED)
        {  
			WCHAR	lpServerName[MAX_PATH];
			LPWSTR	lpBuffer;
			DWORD	dwIndex = 0;
			INT_PTR	hResult;

			//
			//	Will pop up the addnew dialog. User can type in computer names seperated
			//	by white space. After click on OK, we will parse the computer names and
			//	add them to the selected computer list. No duplicates will be added.
			//
			hResult = DialogBoxParam(g_hDllInstance, MAKEINTRESOURCE(IDD_DIALOG_ADDNEW), hwnd, AddNew_DialogProc, NULL);
			if(g_lpszNewComputers)
			{
				lpBuffer = g_lpszNewComputers;
				while(*lpBuffer)
				{
					lpServerName[dwIndex] = '\0';
					while(*lpBuffer && *lpBuffer != '\t' && *lpBuffer != '\n' && *lpBuffer != '\r' && *lpBuffer != ' ')
						lpServerName[dwIndex++] = *lpBuffer++;
					lpServerName[dwIndex] = '\0';
					if(dwIndex > 0 && LB_ERR == ListBox_FindString(g_wins.hwndListSelectComputers, -1, lpServerName))
						ListBox_AddString(g_wins.hwndListSelectComputers, lpServerName);
					dwIndex = 0;
					while(*lpBuffer && (*lpBuffer == '\t' || *lpBuffer == '\n' || *lpBuffer == '\r' || *lpBuffer == ' '))
						lpBuffer++;
				}
				
				LocalFree((HLOCAL)g_lpszNewComputers);
				g_lpszNewComputers = NULL;
			}
			fHandled = TRUE;
		}
        break;
	case IDOK:
		//
		//	Here we gather all of the information and do the action.
		//
        if (codeNotify == BN_CLICKED)
        {  
			int		cItems = 1024;
			int		lpItems[1024];
			int		cActualItems;
			BOOL	fLogoff = FALSE;
			BOOL	fAbort = FALSE;
			BOOL	fForce = FALSE;
			BOOL	fReboot = FALSE;
			BOOL	fDisconnect = FALSE;
			BOOL	fStandby = FALSE;
			DWORD	dwTimeout = 0;
			DWORD	dwReasonCode = 0;
			WCHAR	lpServerName[MAX_PATH];
			WCHAR	lpMsg[MAX_REASON_COMMENT_LEN] = L"";
			DWORD	dwCnt = 0;
			DWORD	dwActionCode = g_dwActionSelect;
			WCHAR	lpNoPrivilage[MAX_PATH];
			WCHAR	lpNotSupported[MAX_PATH];
			WCHAR	lpRes[MAX_PATH * 2];
			WCHAR	lpFailed[MAX_PATH];
			WCHAR	lpSuccess[MAX_PATH];

			//
			//	The default reason code is 0 and default comment is L"".
			//
			if(IsDlgButtonChecked(hwnd, IDC_CHECKWARNING))
			{
				fForce = FALSE;
				lpServerName[0] = '\0';
				GetWindowText(g_wins.hwndEditTimeout, lpServerName, MAX_PATH);
				if(lstrlen(lpServerName) == 0)
				  dwTimeout = 0;
				else dwTimeout = _wtoi(lpServerName);
			}
			else 
			{
				fForce = TRUE;
			}

			LoadString(g_hDllInstance, IDS_CANNOTGETPRIVILAGE, lpNoPrivilage, MAX_PATH);
			LoadString(g_hDllInstance, IDS_ACTIONNOTSUPPORTED, lpNotSupported, MAX_PATH);
			LoadString(g_hDllInstance, IDS_FAILED, lpFailed, MAX_PATH);
			LoadString(g_hDllInstance, IDS_SUCCEEDED, lpSuccess, MAX_PATH);
			GetWindowText(g_wins.hwndEditComment, lpMsg, MAX_REASON_COMMENT_LEN);

			if(dwActionCode == ACTION_LOGOFF)
			{
				fLogoff = TRUE;
			}
			else if (dwActionCode == ACTION_RESTART)
			{
				fReboot = TRUE;
			}
#if 0
			else if (dwActionCode == ACTION_ABORT)
				fAbort = TRUE;
			else if (dwActionCode == ACTION_STANDBY)
			{
				fStandby = TRUE;
				//lstrcat(lpNotSupported, lpServerName);
				//MessageBox(hwnd, lpNotSupported, NULL, 0);
				break;
			}
			else if (dwActionCode == ACTION_DISCONNECT)
			{
				fDisconnect = TRUE;
				//lstrcat(lpNotSupported, lpServerName);
				//MessageBox(hwnd, lpNotSupported, g_lpszTitleWarning, 0);
				break;
			}
#endif //0
			//
			//	Logoff is only for the local computer.
			//	Everything else will ingored.
			//
			if(fLogoff)
			{
				if (!ExitWindowsEx(fForce ? EWX_LOGOFF : (EWX_LOGOFF | EWX_FORCE),
										   0))
				{
					report_error(GetLastError());
				}
				EndDialog(hwnd, (int) dwDlgResult);
				break;
			}

			if(! g_bAssumeShutdown)
			{
				dwReasonCode = g_lpReasons[g_dwReasonSelect].dwCode;
			}

			dwCnt = ListBox_GetCount(g_wins.hwndListSelectComputers);
			if(dwCnt > 0)
			{
				DWORD i;
				for(i = 0; i < dwCnt; i++)
				{
					ListBox_GetText(g_wins.hwndListSelectComputers, i, lpServerName);


					//
					// Get all privileges so that we can shutdown the machine.
					//
					if( !enable_privileges(lpServerName, fLogoff))
					{
						report_error( GetLastError( ));
						wcscpy(lpRes, lpNoPrivilage);
						wcscat(lpRes, L": ");
						wcscat(lpRes, lpServerName);
						wcscat(lpRes, L"\n");
						WriteToConsole(lpRes);
						continue;
					}

					//
					// Do the work.
					//
					if( fAbort )
					{
						if( !AbortSystemShutdown( lpServerName ))
						{
							report_error( GetLastError( ));
						}
					}
					else
					{
						//
						// Do the normal form.
						//
						if( !InitiateSystemShutdownEx( lpServerName,
														lpMsg,
														dwTimeout,
														fForce,
														fReboot,
														dwReasonCode ))
						{
							report_error( GetLastError( ));
							wcscpy(lpRes, lpFailed);
							wcscat(lpRes, L": ");
							wcscat(lpRes, lpServerName);
							wcscat(lpRes, L"\n");
							WriteToConsole(lpRes);
						}
						else
						{
							wcscpy(lpRes, lpSuccess);
							wcscat(lpRes, L": ");
							wcscat(lpRes, lpServerName);
							wcscat(lpRes, L"\n");
							WriteToConsole(lpRes);
						}
					}

					
				}
			}
			else
			{
				//
				//	We will keep the dialog up in case user forget to add computers.
				//
				LoadStringW(g_hDllInstance, IDS_EMPTYLISTMSG, lpMsg, MAX_REASON_COMMENT_LEN);
				MessageBoxW(hwnd, lpMsg, g_lpszTitleWarning, 0);
				break;
			}
			EndDialog(hwnd, (int) dwDlgResult);
		}
        break;
	case IDC_CHECKWARNING:
		//
		//	The checkbutton state decides the state of the timeout edit box.
		//
        if (codeNotify == BN_CLICKED)
        {  
			if(BST_CHECKED == IsDlgButtonChecked(hwnd, IDC_CHECKWARNING))
			{
				EnableWindow(g_wins.hwndEditTimeout, TRUE);
			}
			else 
			{
				EnableWindow(g_wins.hwndEditTimeout, FALSE);
			}
			fHandled = TRUE;
		}
        break;
	case IDC_BUTTONBROWSE:
		//
		//	Simply pop up the browse dialog. That dialog will be responsible
		//	for adding the user selection to the selected computer list.
		//
        if (codeNotify == BN_CLICKED)
        {  
			//DialogBoxParam(g_hDllInstance, MAKEINTRESOURCE(IDD_DIALOG_BROWSE), hwnd, Browse_DialogProc, NULL);
			HRESULT hr;
			ICommonQuery* pcq;
			OPENQUERYWINDOW oqw = { 0 };
			DSQUERYINITPARAMS dqip = { 0 };
			IDataObject *pdo;

			FORMATETC fmte = {(CLIPFORMAT)RegisterClipboardFormat(CFSTR_DSOBJECTNAMES), 
							  NULL,
							  DVASPECT_CONTENT, 
							  -1, 
							  TYMED_HGLOBAL};
			FORMATETC fmte2 = {(CLIPFORMAT)RegisterClipboardFormat(CFSTR_DSQUERYPARAMS), 
							  NULL,
							  DVASPECT_CONTENT, 
							  -1, 
							  TYMED_HGLOBAL};
			STGMEDIUM medium = { TYMED_NULL, NULL, NULL };

			DSOBJECTNAMES *pdon;
			DSQUERYPARAMS *pdqp;

			CoInitialize(NULL);

			//
			// Windows 2000: Always use IID_ICommonQueryW explicitly. IID_ICommonQueryA is not supported.
			//
			hr = CoCreateInstance(CLSID_CommonQuery, NULL, CLSCTX_INPROC_SERVER, IID_ICommonQuery, (void**)&pcq);
			if (FAILED(hr)) {
				//
				// if failed we fall back on our browse dialog.
				//
				CoUninitialize();
				DbgPrint("Cannot create ICommonQuery, fallback on simple browse.\n");
				DialogBoxParam(g_hDllInstance, MAKEINTRESOURCE(IDD_DIALOG_BROWSE), hwnd, Browse_DialogProc, NULL);
				break;
			}

			//
			// Initialize the OPENQUERYWINDOW structure to indicate 
			// we want to do a Directory Service
			// Query, the default form is printers and the search 
			// should start once the window is initialized.
			//
			oqw.cbStruct = sizeof(oqw);
			oqw.dwFlags = OQWF_OKCANCEL|OQWF_DEFAULTFORM|OQWF_HIDEMENUS|OQWF_REMOVEFORMS;
			oqw.clsidHandler = CLSID_DsQuery;
			oqw.pHandlerParameters = &dqip;
			oqw.clsidDefaultForm = CLSID_DsFindComputer;
 
			//
			// Now initialize the handler specific parameters, 
			// in this case, the File/Save menu item is removed
			//
			dqip.cbStruct = sizeof(dqip);
			dqip.dwFlags = DSQPF_NOSAVE;
			

			//
			// Call OpenQueryWindow, it will block until 
			// the Query Window is dismissed,
			//
			hr = pcq->OpenQueryWindow(hwnd, &oqw, &pdo);
			if (FAILED(hr)) {
				//
				// if failed we fall back on our browse dialog.
				//
				pcq->Release();
				CoUninitialize();
				DialogBoxParam(g_hDllInstance, MAKEINTRESOURCE(IDD_DIALOG_BROWSE), hwnd, Browse_DialogProc, NULL);
				break;
			}

			if (!pdo) {
				//
				// if cancelled,nothing needs to be done.
				//
				pcq->Release();
				CoUninitialize();
				break;
			}

			//
			// Get the CFSTR_DSOBJECTNAMES data. For each selected, the data
			// includes the object class and an ADsPath to the selected object.
			//
			hr = pdo->GetData(&fmte, &medium);

			if(! FAILED(hr))
			{
				pdon = (DSOBJECTNAMES*)GlobalLock(medium.hGlobal);
		
				if ( pdon )
				{
					WCHAR			szName[MAX_PATH];
					LPWSTR			lpsz = NULL;
					UINT			i;

					for (i = 0; i < pdon->cItems; i++) 
					{
						if(!GetComputerNameFromPath((LPWSTR) ((PBYTE) pdon + pdon->aObjects[i].offsetName), szName))
							continue;

						//
						//	We don't add dups.
						//
						if(LB_ERR == ListBox_FindString(g_wins.hwndListSelectComputers, -1, szName))
						{
							ListBox_AddString(g_wins.hwndListSelectComputers, szName);
						}
					}
 
					GlobalUnlock(medium.hGlobal);
				}
				else
				{
					DbgPrint("GlobalLock on medium failed.\n");
				}
				ReleaseStgMedium(&medium);
			}
			else
			{
				DbgPrint("pdo->GetData failed: 0x%x\n", hr);
			}
 
			//
			//	Release resources.
			//
			pdo->Release();
			pcq->Release();

			CoUninitialize();
			fHandled = TRUE;
		}
        break;
	case IDC_COMBOOPTION:
		//
		//	Here is where you select shutdown reasons.
		//
        if (codeNotify == CBN_SELCHANGE)
        {  
			WCHAR name[MAX_REASON_NAME_LEN + 1];
			DWORD dwIndex;

			GetWindowText(g_wins.hwndComboOption, (LPWSTR)&name, MAX_REASON_NAME_LEN);
			for(dwIndex = 0; dwIndex < g_dwReasons; dwIndex++)
			{
				if(lstrcmp(name, g_lpReasons[dwIndex].lpName) == 0)
				{
					SetWindowTextW(g_wins.hwndStaticDesc, g_lpReasons[dwIndex].lpDesc);
					g_dwReasonSelect = dwIndex;
					AdjustWindowState();
					break;
				}
			}
			fHandled = TRUE;
		}
        break;
	case IDC_COMBOACTION:
		//
		//	Select user action here.
		//	according to the action. some item will be disabled or enabled.
		//
        if (codeNotify == CBN_SELCHANGE)
        {  
			WCHAR name[MAX_PATH];
			DWORD dwIndex;

			GetWindowText(g_wins.hwndComboAction, (LPWSTR)&name, MAX_PATH);
			for(dwIndex = 0; dwIndex < g_nActions; dwIndex++)
			{
				if(lstrcmp(name, g_lppszActions[dwIndex]) == 0)
				{
					g_dwActionSelect = dwIndex;
					AdjustWindowState();
					break;
				}
			}
			fHandled = TRUE;
		}
        break;
    }
    return fHandled;
}

//
//	Command handler for the addnew dialog.
//	It simply copy the text into a allocated buffer when OK is clicked.
//
BOOL AddNew_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
{
    BOOL		fHandled = FALSE;
    DWORD		dwDlgResult = 0;
	HINSTANCE	h;

    switch (id)
    {
    case IDOK:
        if (codeNotify == BN_CLICKED)
        {  
			HWND hwndEdit;
			DWORD dwTextlen = 0;

			hwndEdit = GetDlgItem(hwnd, IDC_EDIT_ADDCOMPUTERS_COMPUTERS);
			if(hwndEdit != NULL)
			{
				dwTextlen = Edit_GetTextLength(hwndEdit);
				if(dwTextlen)
				{
					g_lpszNewComputers = (LPWSTR)LocalAlloc(LMEM_FIXED, sizeof(TCHAR) * (dwTextlen + 1));
					if(g_lpszNewComputers){
						Edit_GetText(hwndEdit, g_lpszNewComputers, dwTextlen + 1);
					}
				}
			}
			EndDialog(hwnd, (int) dwDlgResult);
        }
        break;
	case IDCANCEL:
        if (codeNotify == BN_CLICKED)
        {  
			EndDialog(hwnd, (int) dwDlgResult);
        }
        break;
	}
    return fHandled;
}

//
//Command handler for the browse dialog.
//
BOOL Browse_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
{
    BOOL		fHandled = FALSE;
    DWORD		dwDlgResult = 0;
	HINSTANCE	h;

    switch (id)
    {
    case IDOK:
		//
		//	Get selected computer names and add them to
		//	selected computer list. No dups.
		//
        if (codeNotify == BN_CLICKED)
        {  
			int cItems = 1024;
			int lpItems[1024];
			int cActualItems;
			HWND hwndFromList;
			WCHAR lpServerName[MAX_PATH];

			hwndFromList = GetDlgItem(hwnd, IDC_LISTNETWORKCOMPUTERS);
			assert(hwndFromList != NULL);
			cActualItems = ListBox_GetSelItems(hwndFromList, cItems, lpItems);
			if(cActualItems > 0)
			{
				int i;
				for(i = 0; i < cActualItems; i++)
				{
					ListBox_GetText(hwndFromList, lpItems[i], lpServerName);
					if(IsEmpty(lpServerName))
						continue;
					if(LB_ERR == ListBox_FindString(g_wins.hwndListSelectComputers, -1, lpServerName))
						ListBox_AddString(g_wins.hwndListSelectComputers, lpServerName);
				}
			}
			
			EndDialog(hwnd, (int) dwDlgResult);
			fHandled = TRUE;
        }
        break;
	case IDCANCEL:
		if (codeNotify == BN_CLICKED)
		{
			EndDialog(hwnd, (int)0);
			fHandled = TRUE;
		}
		break;
	case IDC_BUTTON_REFRESH:
		//
		//	List the computers in the specified domain.
		//
		if (codeNotify == BN_CLICKED)
		{
			WCHAR	domain[MAX_PATH];
			HWND	hwndDomain;
			HWND	hwndComputers;
			HWND	hwndProgress;

			hwndDomain		= GetDlgItem(hwnd, IDC_EDITDOMAIN);
			hwndComputers	= GetDlgItem(hwnd, IDC_LISTNETWORKCOMPUTERS);
			hwndProgress	= GetDlgItem(hwnd, IDC_STATIC_PROGRESS);
			assert(hwndDomain != NULL && hwndComputers != NULL && hwndProgress != NULL);

			while(ComboBox_DeleteString(hwndComputers, 0));
			lstrcpy(domain, g_lpszDefaultDomain);
			Edit_GetText(hwndDomain, domain, MAX_PATH);
			GetNetworkComputers(hwndComputers, hwndProgress, domain);
			
			fHandled = TRUE;
		}
		break;
	}
    return fHandled;
}