Имя пользователя:
Пароль:  
Помощь | Регистрация | Забыли пароль?  | Правила  

Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » C/C++ *Example* | "Продвинутое" отключение XP

Ответить
Настройки темы
C/C++ *Example* | "Продвинутое" отключение XP

Аватара для hasherfrog

Старый параноик


Сообщения: 2423
Благодарности: 85


Конфигурация

Профиль | Отправить PM | Цитировать


Несколько вопросов обсуждались в разное время на форуме.
1. Как заставить ХР предупредить о подключенных соединениях при выключении машины;
2. Как прервать отключение машины, если что-то забыл сделать.

Поскольку я сейчас чем-то подобным занимаюсь, набросал небольшую программку, предназначенную для отключения XP машин. Её можно использовать вместо стандарного Shutdown в меню Пуск.

Код: Выделить весь код
#ifndef UNICODE 
#define UNICODE 
#endif 
 
#include <stdio.h> 
#include <string.h> 
#include <stdarg.h> 
#include <windows.h> 
#include <winuser.h> 
#include <lm.h> 
 
// собранная информация о сессиях 
static wchar_t * pszSessions = NULL; 
 
// добавление очередной записи к хранилищу 
void save_session(const wchar_t * fmt, ...) 
{     
    // размер очередной строки, ориентировочно ~100 байт 
    int size = 100; 
    // память под очередную строку 
    wchar_t *p = (wchar_t *) malloc(size * sizeof(wchar_t)); 
    // безопасность 
    if (!p) return; p[0] = '\0'; 
    // формируем строку 
    va_list ap; 
    while (1) 
    { 
	// попытаемся вместиться в уже выделенную память 
	va_start(ap, fmt); 
	// реальная длина новой строки 
	int n = _vsnwprintf(p, size, fmt, ap); 
	va_end(ap); 
	// если влезли, ок 
	if (n > -1 && n < size) break; 
	// иначе - увеличиваем буфер под строку 
	size *= 2; 
	if ((p = (wchar_t *) realloc(p, size * sizeof(wchar_t))) == NULL) return; //oops 
    } 
 
    // строку сформирована, надо её добавить к имеющимся 
    size = lstrlen(p); 
    if (pszSessions) size += lstrlen(pszSessions); 
    wchar_t *pn = (wchar_t *)malloc((size + 1)*sizeof(wchar_t)); //eos 
    if (!pn) return; pn[0] = '\0'; 
    //складываем строки 
    if (pszSessions) lstrcpy(pn, pszSessions); 
    lstrcat(pn, p); 
    free(p); 
    free(pszSessions); 
    pszSessions = pn; 
    return; 
} 
 
//int main(int argc, wchar_t *argv[]) 
int WINAPI WinMain(HINSTANCE hInst,HINSTANCE hPrev,LPSTR lpszCmd,int nCmd) 
{ 
    DWORD dwTotalCount = 0; 
    NET_API_STATUS nStatus; 
     
    // начальная фраза сообщения 
    save_session(L"%s", L"Warning! Some sessions are not closed:\n\n"); 
   
    // для всех имеющихся соединений 
    do 
    { 
	LPSESSION_INFO_10 pBuf = NULL; 
	DWORD dwEntriesRead = 0; 
	DWORD dwTotalEntries = 0; 
	DWORD dwResumeHandle = 0; 
	 
	// вызываем очередной NetSessionEnum 
	nStatus = NetSessionEnum(NULL,	//всё локально 
				NULL,	//для всех сессий 
				NULL, 	//для всех пользователей 
				10,	//тип запроса хост-юзер-время-простой 
				(LPBYTE*)&pBuf,	//данные на выходе 
				MAX_PREFERRED_LENGTH, //длина записи 
				&dwEntriesRead,	//сколько считано 
				&dwTotalEntries,		//сколько всего 
				&dwResumeHandle);	//номер запроса 
	 
	// проверяем результат 
	if ((nStatus == NERR_Success) || (nStatus == ERROR_MORE_DATA)) 
	{ 
	    // запоминаем сессии клиентов 
	    if (LPSESSION_INFO_10 pTmpBuf = pBuf) 
		for (int i = 0; i < dwEntriesRead; i++) 
		    if (pTmpBuf) 
		    { 
			save_session(L"Client: %s\tUser: %s\tActive: %d\tIdle: %d\n", 
				     pTmpBuf->sesi10_cname, pTmpBuf->sesi10_username, 
				     pTmpBuf->sesi10_time, pTmpBuf->sesi10_idle_time); 
			pTmpBuf++; 
			dwTotalCount++; 
		    } 
	} 
 
	// идём на следующий запрос 
	if (pBuf) 
	{ 
	    NetApiBufferFree(pBuf); 
	    pBuf = NULL; 
	} 
    } while (nStatus == ERROR_MORE_DATA); 
     
    // если есть сессии, сообщаем об этом выключателю 
    if (dwTotalCount) 
    { 
	// финальная часть сообщения 
	save_session(L"%s", L"\nDo you wish to cancel shutdown?\n"); 
	// вывод сообщения 
	if (IDYES == MessageBox(NULL, pszSessions, L"Warning!", MB_YESNO)) return 0; 
    } 
 
    //чистим память от сообщения - оно нам больше не нужно 
    free(pszSessions); 
     
    HANDLE hToken;              // handle to process token 
    TOKEN_PRIVILEGES tkp;       // pointer to token structure 
 
    // Get the current process token handle so we can get shutdown privilege. 
    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, 
			  &hToken)) return 1; 
     
    // Get the LUID for shutdown privilege. 
    LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid); 
    tkp.PrivilegeCount = 1;  // one privilege to set 
    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 
     
    // Get shutdown privilege for this process. 
    AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES) NULL, 0); 
    if (GetLastError() != ERROR_SUCCESS) return 1; 
     
    // Вывести окошечко обратного отсчёта 
    if (!InitiateSystemShutdown( 
	    NULL,    // shut down local computer 
	    L"We starts system shutdown.\nIf You have forget to do something, press " 
	    L"Ok in message box for stop shutdown.",   // message for user 
	    20,      // time-out period 
	    FALSE,   // ask user to close apps 
	    FALSE)) //shutdown, no reboot 
	return 1; 
     
    // Disable shutdown privilege. 
    tkp.Privileges[0].Attributes = 0; 
    AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES) NULL, 0); 
     
    MessageBox(NULL, L"Press OK to stop shutdown", L"Haves forget somehing?", 
	       MB_OK | MB_SYSTEMMODAL); 
    // если мы сюда попали, надо отключать шатдаун 
    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, 
			  &hToken)) return 1; 
    LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid); 
    tkp.PrivilegeCount = 1; 
    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 
    AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0); 
    if (GetLastError() != ERROR_SUCCESS) return 1; 
     
    // Prevent the system from shutting down. 
    if ( !AbortSystemShutdown(NULL) ) return 1; 
    // Disable shutdown privilege. 
    tkp.Privileges[0].Attributes = 0; 
    AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES) NULL, 0); 
     
    return 0; 
}
FAQ

Q. И как использовать?
A. Компилите. Кладёте ярлык на рабочий стол. При необходимости выключить машину жмёте не Пуск->Выключить, а щёлкаете по этому ярлыку. Он Вас спросит про активные подключения (если они есть). Потом даст 20 секунд на раздумья. Потом выключится.

Q. Почему C++, а не, скажем, VBS?
A. Потому что C++ мне ближе.

Q. Как компилить?
A. Я использую Visual C++ Toolkit. Компиляция:
cl enum_shares.cpp /GA /O1 /link /defaultlib:netapi32.lib /defaultlib:advapi32.lib /defaultlib:user32.lib

Q. А в 9х будет работать?
A. Нет. В 9х сообщение об активных подключениях и так выдается.

Q. Почему UNICODE?
A.Потому что NetSessionEnum

Q. Что так странно (в смысле стиля написания) сформирован текст и комментарии?
A. Потому что при написании использовались фрагменты из PSDK.

Q. А есть ли бинарник?
A. Есть. Тут пока лежит.

Q. Можно использовать в моих программах куски текста?
A. Да, сделано специально для посетителей www.oszone.net

Q. У меня ещё вопросы...
A. Задавайте здесь, я отвечу.

Это сообщение посчитали полезным следующие участники:

Отправлено: 15:50, 28-06-2004

 

Аватара для hasherfrog

Старый параноик


Сообщения: 2423
Благодарности: 85

Профиль | Отправить PM | Цитировать


Есть маленькая "учечка памяти". Чтобы убрать:
Код: Выделить весь код
...
    // если есть сессии, сообщаем об этом выключателю 
    if (dwTotalCount) 
    { 
	// финальная часть сообщения 
	save_session(L"%s", L"\nDo you wish to cancel shutdown?\n"); 
	// вывод сообщения 
	if (IDYES == MessageBox(NULL, pszSessions, L"Warning!", MB_YESNO)) 
        { 
            return 0; 
            free(pszSessions); // <--------- добавить. 
         } 
    } 
 
    //чистим память от сообщения - оно нам больше не нужно 
    free(pszSessions); 
    ...
Это сообщение посчитали полезным следующие участники:

Отправлено: 09:36, 29-06-2004 | #2



Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети.

Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля.


Старожил


Сообщения: 185
Благодарности: 1

Профиль | Отправить PM | Цитировать


hasherfrog
Хорошая программа.

Вопрос - как можно отслеживать все подключения (NetSessionEnum) и открытия файлов (NetFileEnum) для создания, скажем, своего журнала событий.
Если вызывать эти функции по таймеру - есть вероятность, что какое-то подключение или открытие файла успеет открыться и закрыться.
Возможно, нужно использовать механизм hook-ов, *можно ли сделать это без существенного снижения производительности системы?

-------
I like to move it, move it.


Отправлено: 21:13, 29-06-2004 | #3


Аватара для hasherfrog

Старый параноик


Сообщения: 2423
Благодарности: 85

Профиль | Отправить PM | Цитировать


DAnG
Таймер однозначно "не катит". Хуки - это да . Снижение производительности будет очень незначительным. У Руссиновича на www.sysinternals.com есть исходник, правда, для линукса. Там же есть бинарники FileMon. Если залезть туда (через HIEW, или ещё как) и посмотреть таблицу используемых системных функций, то хуки наверняка найдутся. Впрочем, я не проверял, так что это только предположение!

Отправлено: 09:02, 30-06-2004 | #4


Аватара для hasherfrog

Старый параноик


Сообщения: 2423
Благодарности: 85

Профиль | Отправить PM | Цитировать


Некоторые замечания сделаны здесь.

Отправлено: 14:57, 30-06-2004 | #5


Старожил


Сообщения: 185
Благодарности: 1

Профиль | Отправить PM | Цитировать



hasherfrog
Кучу времени пользуюсь и tcpview и regmon и filemon, а на сайт авторов так и не заглянул. Позор.
Очень много полезных вещей и с исходниками по windows, что редкость. Спасибо, огромное!.

-------
I like to move it, move it.


Отправлено: 03:53, 01-07-2004 | #6


Аватара для Guest

Guest


Профиль | Цитировать


Для написания таких программ лучше использовать Visual Basic.

Добавлено:

Кстати, кому надо, могу выложить исходник. Написал программку на VB, она умеет выключать/перезагружать комп, да ещё с такими наворотами (в смысле оформления)...

Добавлено:

И ещё, она может выключать/перезагружать комп в заданное время.

Отправлено: 13:02, 15-08-2004 | #7


Аватара для [mzd]

Линуксоид-стакановец


Сообщения: 2391
Благодарности: 186

Профиль | Отправить PM | Цитировать


Guest
Для системного программирования, IMHO, лучше С++ ничего нет.
VB для этого не разрабатывался


[s]Исправлено: [mzd], 19:20 15-08-2004[/s]

-------
Живя в реальном мире, стремись к невероятному... Эрнесто Че Гевара
Everybody lies. (c) House M.D.
Базовая настройка Ubuntu. Документация для новичка.
Руководство по установке, начальной настройке и основам использования операционной системы Ubuntu


Отправлено: 19:18, 15-08-2004 | #8


Новый участник


Сообщения: 4
Благодарности: 0

Профиль | Сайт | Отправить PM | Цитировать


Тема все еще акуальна а ссылки на скомпилиную прогу от hasherfrog уже мертвые
можно ли перезалить или на мыло stasisСОБАКАpisem.net сбросить? или кто перекомпилит поновой?

-------
-=wWw=-


Отправлено: 20:41, 12-09-2006 | #9


Аватара для hasherfrog

Старый параноик


Сообщения: 2423
Благодарности: 85

Профиль | Отправить PM | Цитировать


Извиняюсь за задержку, в отпуске был.
http://hasherfrog.nm.ru/Trash/smrtdown.exe

Отправлено: 11:35, 25-09-2006 | #10



Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » C/C++ *Example* | "Продвинутое" отключение XP

Участник сейчас на форуме Участник сейчас на форуме Участник вне форума Участник вне форума Автор темы Автор темы Шапка темы Сообщение прикреплено

Похожие темы
Название темы Автор Информация о форуме Ответов Последнее сообщение
7 / 2008 R2 - Отключение окна "Установить программное обеспечение для данного устройства" SystemIntegrator Автоматическая установка Windows 11 / 10 / 8 / 7 / Vista 12 19-06-2024 14:36
Интерфейс - [решено] Как удалить папку "Моя музыка","Мои Картинки", "Мое видео"? verdix Microsoft Windows 2000/XP 3 03-10-2009 23:46
Запретить/удалить пункт "Programs" ("Программы") из меню кнопки "Start" ("Пуск") submaster Microsoft Windows NT/2000/2003 5 13-09-2006 12:29
Как убрать значек "безопасное отключение устройства" Guest Microsoft Windows 2000/XP 6 24-03-2004 18:14
[решено] Реестр - Отключение сообщения "Очистка диска" bizart Microsoft Windows 2000/XP 1 13-02-2004 08:29




 
Переход