Программа-сервис Windows XP, делающая снимки экрана, после переноса на Windows 7 начала сохранять вместо снимков просто белый фон.
Чтобы использовать основанную на коде ниже программу ru1smake, распакуйте архив в отдельную папку, установите ее как сервис (командой ru1smake.exe /install), задайте параметры в конфигурационном файле ru1smake.conf и запускайте через диспетчер служб. Удаление – командой ru1smake.exe /uninstall. Программа будет автоматически делать снимки экрана согласно указанным в конфиге параметрам.
Скачать программу ru1smake
версия 0.1 (07.08.10) | 0.3 Мб | stable
Дело в том, что начиная с Windows Vista, служба, запущенная от имени SYSTEM, более не может взаимодействовать с рабочим столом – службы теперь запускаются в изолированном сеансе (сессии) и загрузка своего процесса приведет к попытке запуска в неверном (вошедшего в систему пользователя) сеансе. Решить проблему можно, получив сессию залогинившегося пользователя. Вкратце, этот код делает следующее:
- Получает токен вошедшего в систему в данный момент пользователя, используя функцию WtsGetActiveConsoleSessionID
- Далее получает пользовательский токен, назначенный процессу (токен для службы от имени SYSTEM)
- Затем этот токен дублируется
- У скопированного токена изменяется сеанс (на вошедшего пользователя)
- Используя CreateProcessAsUser запускается процесс с измененным пользовательским токеном
Процесс с системными правами, но будучи запущенным от имени вошедшего в систему пользователя в Windows 7, также позволит корректно работать GUI-программе как и любой другой.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
#include <iostream> #include "Windows.h" #include <UserEnv.h> #include <WtsApi32.h> #include <Tlhelp32.h> #include <Tchar.h> #include <string> #pragma comment(lib,"WtsApi32.lib") #pragma comment(lib,"UserEnv.lib") void convertWStringToCharPtr(_In_ std::wstring input, _Out_ char* outputString) { size_t outputSize = input.length() + 1; // +1 for null terminator outputString = new char[outputSize]; size_t charsConverted = 0; const wchar_t* inputW = input.c_str(); wcstombs_s(&charsConverted, outputString, outputSize, inputW, input.length()); } BOOL LaunchApplication(LPCWSTR Filename) { PROCESS_INFORMATION pi; STARTUPINFO si; BOOL bResult = FALSE; DWORD dwSessionId, winlogonPid; HANDLE hUserToken, hUserTokenDup, hPToken, hProcess; DWORD dwCreationFlags; // Log the client on to the local computer. dwSessionId = WTSGetActiveConsoleSessionId(); // Find the winlogon process PROCESSENTRY32 procEntry; HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hSnap == INVALID_HANDLE_VALUE) { return 1; } procEntry.dwSize = sizeof(PROCESSENTRY32); if (!Process32First(hSnap, &procEntry)) { return 1; } do { char exeFile[13] = "winlogon.exe"; convertWStringToCharPtr(procEntry.szExeFile, exeFile); const char* cExeFile = exeFile; if (_stricmp(cExeFile, "winlogon.exe") == 0) { // We found a winlogon process... // make sure it's running in the console session DWORD winlogonSessId = 0; if (ProcessIdToSessionId(procEntry.th32ProcessID, &winlogonSessId) && winlogonSessId == dwSessionId) { winlogonPid = procEntry.th32ProcessID; break; } } } while (Process32Next(hSnap, &procEntry)); WTSQueryUserToken(dwSessionId, &hUserToken); dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE; ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); const char* desk = "Winsta0\\Default"; size_t size = strlen(desk) + 1; wchar_t* w_desk = new wchar_t[size]; size_t outSize; mbstowcs_s(&outSize, w_desk, size, desk, size - 1); si.lpDesktop = w_desk; ZeroMemory(&pi, sizeof(pi)); TOKEN_PRIVILEGES tp; LUID luid; hProcess = OpenProcess(MAXIMUM_ALLOWED, FALSE, winlogonPid); if (!::OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_ADJUST_SESSIONID | TOKEN_READ | TOKEN_WRITE, &hPToken)) { printf("OpenProcessToken: %u\n", GetLastError()); } if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) { printf("LookupPrivilegeValue: %u\n", GetLastError()); } tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; DuplicateTokenEx(hPToken, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &hUserTokenDup); SetTokenInformation(hUserTokenDup, TokenSessionId, (void*)dwSessionId, sizeof(DWORD)); if (!AdjustTokenPrivileges(hUserTokenDup, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, NULL)) { printf("AdjustTokenPrivileges: %u\n", GetLastError()); } if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) { printf("Token does not have the provilege\n"); } LPVOID pEnv = NULL; if (CreateEnvironmentBlock(&pEnv, hUserTokenDup, TRUE)) { dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT; } else pEnv = NULL; bResult = CreateProcessAsUser( hUserTokenDup, // client's access token Filename, // file to execute NULL, // command line NULL, // pointer to process SECURITY_ATTRIBUTES NULL, // pointer to thread SECURITY_ATTRIBUTES FALSE, // handles are not inheritable dwCreationFlags, // creation flags pEnv, // pointer to new environment block NULL, // name of current directory &si, // pointer to STARTUPINFO structure &pi // receives information about new process ); //Perform All the Close Handles tasks CloseHandle(hProcess); CloseHandle(hUserToken); CloseHandle(hUserTokenDup); CloseHandle(hPToken); return 0; } |
11.04.2010
29.05.2010
19.07.2010
09.10.2010
30.10.2010
11.12.2010
12.12.2010
10.07.2011
17.07.2011
18.09.2011
10.02.2012
12.02.2012
04.02.2013
24.03.2013
26.03.2013
07.05.2014
28.08.2014
19.02.2015
25.02.2015
28.02.2015
19.02.2016