windows-nt/Source/XPSP1/NT/ds/security/gina/shutdown/main.cpp

1921 lines
47 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
#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;
}