|
|
#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; }
|