gpt4 book ai didi

c++ - EnumDesktopWindows 错误 : (183) Cannot create a file when that file already exists

转载 作者:太空宇宙 更新时间:2023-11-04 11:31:51 24 4
gpt4 key购买 nike

任何人都知道为什么在调用 EnumDesktopWindows 时返回 183

这个进程是一个运行在System LocalService中的服务

我试图将窗口放在顶部,因为进程开始时最小化。

感谢帮助

我的代码:

BOOL CALLBACK EnumWindowsProc( HWND hwnd, LPARAM lParam ) 
{
DWORD dwPID;
GetWindowThreadProcessId( hwnd, &dwPID );

if( dwPID == lParam ) {
SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE );
SwitchToThisWindow(hwnd, true);
SetFocus( hwnd );
return FALSE;
}

return TRUE;
}

BOOL CALLBACK EnumDesktopProc(LPTSTR lpszDesktop, LPARAM lParam) {
HDESK hDesk = OpenDesktop(lpszDesktop, NULL, FALSE, GENERIC_ALL);

if(hDesk != NULL) {

if(!EnumDesktopWindows(hDesk,&EnumWindowsProc, lParam)) {
//This call returns (183) Cannot create a file when that file already exists
}

CloseDesktop(hDesk);
}

return TRUE;
}


BOOL CALLBACK EnumWindowStationProc(LPTSTR lpszWindowStation, LPARAM lParam)
{

HWINSTA hWinStat = OpenWindowStation(lpszWindowStation,FALSE,WINSTA_ENUMDESKTOPS|WINSTA_ENUMERATE);

if(hWinStat) {
SetProcessWindowStation(hWinStat);
EnumDesktops(hWinStat,&EnumDesktopProc,lParam);
CloseWindowStation(hWinStat);
}

return TRUE;
}


bool Utils::execIntoDifferentSession(const std::wstring &aPath, const std::wstring &aParams, const std::wstring &aMode)
{
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 false;

procEntry.dwSize = sizeof(PROCESSENTRY32);

if (!Process32First(hSnap, &procEntry))
return false;

do {
if (_wcsicmp(procEntry.szExeFile, L"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);
si.lpDesktop = L"winsta0\\default";
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOWNORMAL|SW_RESTORE;

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))
{
return false;
}

if (!LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&luid))
return false;

tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

DuplicateTokenEx(hPToken,MAXIMUM_ALLOWED,NULL,SecurityIdentification,TokenPrimary,&hUserTokenDup);

//Adjust Token privilege
SetTokenInformation(hUserTokenDup,TokenSessionId,(void*)dwSessionId,sizeof(DWORD));

if (!AdjustTokenPrivileges(hUserTokenDup,FALSE,&tp,sizeof(TOKEN_PRIVILEGES),(PTOKEN_PRIVILEGES)NULL,NULL))
return false;

if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
return false;

LPVOID pEnv = NULL;

if(CreateEnvironmentBlock(&pEnv,hUserTokenDup,TRUE))
dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT;
else
pEnv = NULL;

// Launch the process in the client's logon session.

std::wstring params = aParams;
std::wstring path = aPath;

if(aMode == L"select") {
TCHAR infoBuffer[MAX_PATH];
GetSystemWindowsDirectory(infoBuffer, MAX_PATH);
std::wstring windowsDir(infoBuffer);

path = windowsDir+L"\\explorer.exe";
params = L" /n, /select,"+replaceString(aPath, L"\\\\", L"\\");
}

bResult = CreateProcessAsUser(
hUserTokenDup, // client's access token
path.c_str(), // file to execute
params.length() > 0 ? stringToLPWSTR(wideToUtf8(params)) : 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
);

EnumWindowStations(&EnumWindowStationProc, (LPARAM)(pi.dwProcessId));

// End impersonation of client.

//GetLastError Shud be 0

int rv = GetLastError();

//Perform All the Close Handles task

CloseHandle(hProcess);
CloseHandle(hUserToken);
CloseHandle(hUserTokenDup);
CloseHandle(hPToken);

return !rv;
}

最佳答案

错误 183 是 ERROR_ALREADY_EXISTSEnumDesktopWindows() 不会设置该错误,因此它一定是早期 API 调用的遗留问题。如果您阅读文档,会这样说:

http://msdn.microsoft.com/en-us/library/windows/desktop/ms682615.aspx

You must ensure that the callback function sets SetLastError if it fails.

http://msdn.microsoft.com/en-us/library/windows/desktop/ms682614.aspx

If the callback function fails, the return value is zero. The callback function can call SetLastError to set an error code for the caller to retrieve by calling GetLastError.

所以尝试更像这样的东西:

struct WndInfo
{
DWORD dwProcessID;
HWND hWnd;
};

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
WndInfo *pInfo = (WndInfo*) lParam;

DWORD dwPID;
GetWindowThreadProcessId(hwnd, &dwPID);

if (dwPID == pInfo->dwProcessID)
{
pInfo->hWnd = hwnd;
SetLastError(0);
return FALSE;
}

return TRUE;
}

BOOL CALLBACK EnumDesktopProc(LPTSTR lpszDesktop, LPARAM lParam)
{
HDESK hDesk = OpenDesktop(lpszDesktop, NULL, FALSE, GENERIC_ALL);
if (hDesk != NULL)
{
if (!EnumDesktopWindows(hDesk, &EnumWindowsProc, lParam))
{
if (GetLastError() != 0)
{
// handle error as needed...
}
}

CloseDesktop(hDesk);

WndInfo *pInfo = (WndInfo*) lParam;
if (pInfo->hWnd != NULL)
{
SetLastError(0);
return FALSE;
}
}

return TRUE;
}

BOOL CALLBACK EnumWindowStationProc(LPTSTR lpszWindowStation, LPARAM lParam)
{
HWINSTA hWinStat = OpenWindowStation(lpszWindowStation, FALSE, WINSTA_ENUMDESKTOPS|WINSTA_ENUMERATE);
if (hWinStat != NULL)
{
SetProcessWindowStation(hWinStat);

if (!EnumDesktops(hWinStat, &EnumDesktopProc, lParam))
{
if (GetLastError() != 0)
{
// handle error as needed...
}
}

CloseWindowStation(hWinStat);

WndInfo *pInfo = (WndInfo*) lParam;
if (pInfo->hWnd != NULL)
{
SetLastError(0);
return FALSE;
}
}

return TRUE;
}

HWND findWindowForProcess(DWORD PID)
{
WndInfo info;
info.dwProcessID = PID;
info.hWnd = NULL;

if (!EnumWindowStations(&EnumWindowStationProc, (LPARAM)&info))
{
if (GetLastError() != 0)
{
// handle error as needed...
}
}

return info.hWnd;
}
bool Utils::execIntoDifferentSession(const std::wstring &aPath, const std::wstring &aParams, const std::wstring &aMode)
{
...
bResult = CreateProcessAsUser(...);
if (bResult)
{
HWND hWnd = findWindowForProcess(pi.dwProcessId);
if (hWnd != NULL)
{
SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
SwitchToThisWindow(hWnd, TRUE);
SetFocus(hWnd);
}
}
...
}

话虽如此,由于您真正想要做的只是在特定用户 session 中执行一个新进程,因此您无需为所有这些枚举逻辑操心。您根本不需要找到 WinLogon 进程,您已经从 WTSQueryUserToken() 中获得了用户 token ,因此只需根据需要复制+调整该 token 即可。并且您在窗口枚举中没有做任何有用的事情,新进程在启动时默认情况下不会这样做,所以也摆脱那个逻辑。

然后最后修复您的错误处理(或缺少),以便您可以关闭任何打开的句柄而不泄漏它们。

关于c++ - EnumDesktopWindows 错误 : (183) Cannot create a file when that file already exists,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24418122/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com