Служба сопоставления дисков Windows 8 неправильно распознана службой

Я сталкиваюсь с проблемой в Windows 8, где приложение / служба с повышенными правами, которая олицетворяет вошедшего в систему пользователя, не распознает пути сопоставленных дисков правильно.

У меня есть служба Windows, которую я использую для копирования файлов из / в различные исходные пути / места назначения, включая подключенные сетевые диски. Пути передаются в сервис через XML-файл. Затем служба читает источник и назначение из xml и копирует файл. У меня никогда не было проблем с подключенными дисками в Vista и 7, так как сервис всегда олицетворяет зарегистрированного пользователя, получая токен проводника и все мои CreateFile, ReadFileс и WriteFile работал отлично.

Вот как я выдаю себя за пользователя

сначала я получаю токен сессии, используя следующий код

DWORD GetActiveSessionId(DWORD& ret)
{
ret=0;
DWORD active_session_id = WTSGetActiveConsoleSessionId();
if (IsSessionActive(active_session_id))
{
return active_session_id;
}

DWORD console_session_ID = active_session_id;
active_session_id = -2;
WTS_SESSION_INFO* session_info = NULL;
DWORD num_sessions = 0;
if (WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1,
&session_info, &num_sessions))
{
// Pick the first active session we can find
for (DWORD i = 0 ; i < num_sessions; ++i)
{
if (session_info[i].State == WTSActive)
{
// There is a user logged on to the WinStation associated with the
// session.
active_session_id = session_info[i].SessionId;
break;
}
}
WTSFreeMemory(session_info);
return active_session_id;
}

ret=::GetLastError();
return -2;
}BOOL GetSessionUserToken( HANDLE * phUserToken, DWORD& retCode )
{
if( NULL == phUserToken )
{
return FALSE;
}

BOOL bRet = FALSE;
HANDLE hImpersonationToken = NULL;

BOOL bWin2K = FALSE;
OSVERSIONINFOEX osv;
ZeroMemory( & osv, sizeof( OSVERSIONINFOEX ) );
osv.dwOSVersionInfoSize  = sizeof( OSVERSIONINFOEX );
if( GetVersionEx( (OSVERSIONINFO*) & osv ) )
{
if( 0 == osv.dwMinorVersion && osv.dwMajorVersion == 5)
{
return FALSE;
}
}

DWORD dwActiveSession= CGSSystem::GetActiveSessionId(retCode);

if (dwActiveSession==GSInvalidSessionId)
return FALSE;

if( 0 != WTSQueryUserToken( dwActiveSession, & hImpersonationToken ) )
{
bRet = TRUE;
}
else
{

}DWORD neededSize = 0;
HANDLE *realToken = new HANDLE;
if(GetTokenInformation(hImpersonationToken, (::TOKEN_INFORMATION_CLASS) TokenLinkedToken, realToken, sizeof(HANDLE), &neededSize))
{
CloseHandle(hImpersonationToken);
hImpersonationToken = *realToken;
}
DWORD lastError = GetLastError();
delete realToken;if( TRUE == bRet )
{
bRet = DuplicateTokenEx( hImpersonationToken,
0,
NULL,
SecurityImpersonation,
TokenPrimary,
phUserToken );

CloseHandle( hImpersonationToken );
}

return bRet;
}

Тогда у меня есть CopyFile функция, которая является потоком. Это огромная функция, поэтому я упомяну только важные (олицетворение / безопасность) части.

BOOL CopyFile(LPCTSTR source, LPCTSTR destination)
{

//Some variables initializations
//...

HRESULT hrInternal = CoInitializeSecurity(
NULL,                           //  Allow *all* VSS writers to communicate back!
-1,                             //  Default COM authentication service
NULL,                           //  Default COM authorization service
NULL,                           //  reserved parameter
RPC_C_AUTHN_LEVEL_PKT_PRIVACY,  //  Strongest COM authentication level
RPC_C_IMP_LEVEL_IDENTIFY,       //  Minimal impersonation abilities
NULL,                           //  Default COM authentication settings
EOAC_NONE,                      //  No special options
NULL                            //  Reserved parameter
);

//Initialize security descriptors
SECURITY_DESCRIPTOR    SD;
SECURITY_ATTRIBUTES copyMutexAttrib;
copyMutexAttrib.nLength = sizeof( SECURITY_ATTRIBUTES );
copyMutexAttrib.lpSecurityDescriptor = & SD;
copyMutexAttrib.bInheritHandle = TRUE;

if(!InitializeSecurityDescriptor( & SD, SECURITY_DESCRIPTOR_REVISION ) )
{
//Error handling;
}

// add a NULL disc. ACL to the security descriptor.
//
if( ! SetSecurityDescriptorDacl( & SD, TRUE, (PACL) NULL, FALSE ) )
{
//Error handling;
}

HRESULT hr=S_OK;
hr=ModifyThreadPrivilege( SE_BACKUP_NAME, TRUE , m_hUserToken==NULL ? FALSE : TRUE  );
if (FAILED(hr))
{
//Error Handling and logs
}

hr=S_OK;
hr=ModifyThreadPrivilege( SE_TCB_NAME, TRUE , m_hUserToken==NULL ? FALSE : TRUE  );
if (FAILED(hr))
{
//Error Handling and logs
}
hr=ModifyThreadPrivilege( SE_IMPERSONATE_NAME, TRUE , m_hUserToken==NULL ? FALSE : TRUE  );
if (FAILED(hr))
{
//Error Handling and logs
}

hr=ModifyThreadPrivilege( SE_MANAGE_VOLUME_NAME, TRUE , m_hUserToken==NULL ? FALSE : TRUE  );
if (FAILED(hr))
{
//Error Handling and logs
}

hr=ModifyThreadPrivilege( SE_SYSTEM_PROFILE_NAME, TRUE , m_hUserToken==NULL ? FALSE : TRUE  );
if (FAILED(hr))
{
//Error Handling and logs
}

hr=ModifyThreadPrivilege( SE_DEBUG_NAME, TRUE , m_hUserToken==NULL ? FALSE : TRUE  );
if (FAILED(hr))
{
//Error Handling and logs
}//Other variable initializations
//...

//Create the destination file
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;

HANDLE hFile = ::CreateFile(destination, GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, &sa,
CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH|FILE_FLAG_BACKUP_SEMANTICS, NULL);  //---> creates the file in the wrong location}

и это мой код ModifyThreadPrivilage:

HRESULT ModifyThreadPrivilege(IN LPCTSTR szPrivilege,IN BOOL fEnable,IN BOOL OpenAsSelf)
{
HRESULT hr = S_OK;
TOKEN_PRIVILEGES NewState;
LUID luid;
HANDLE hToken = NULL;

// Open the process token for this process.
if (!OpenThreadToken(GetCurrentThread(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
OpenAsSelf,
&hToken ))
{
int iLast=::GetLastError();
if (iLast != ERROR_NO_TOKEN)
{
return ERROR_FUNCTION_FAILED;
}

/*
* No access token for the thread so impersonate the security context
* of the process.
*/
if (!ImpersonateSelf(SecurityImpersonation))
{
return ERROR_FUNCTION_FAILED;
}

if (!OpenThreadToken(GetCurrentThread(),
TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,
FALSE,
&hToken))
{
return ERROR_FUNCTION_FAILED;
}

}

// Get the local unique ID for the privilege.
if ( !LookupPrivilegeValue( NULL,
szPrivilege,
&luid ))
{
CloseHandle( hToken );
printf("Failed LookupPrivilegeValue\n");
return ERROR_FUNCTION_FAILED;
}

// Assign values to the TOKEN_PRIVILEGE structure.
NewState.PrivilegeCount = 1;
NewState.Privileges[0].Luid = luid;
NewState.Privileges[0].Attributes =
(fEnable ? SE_PRIVILEGE_ENABLED : 0);// Adjust the token privilege.
if (!AdjustTokenPrivileges(hToken,
FALSE,
&NewState,
0,
NULL,
NULL))
{
hr = ERROR_FUNCTION_FAILED;
}

// Close the handle.
CloseHandle(hToken);

return hr;
}

В Windows 8 и когда место назначения является подключенный диск, как "Z:\MyFile.txt" он записывает файл в неправильное место, вот так:

Я подключил сетевой диск Z: который сопоставлен с
\\nsa\public\myfolder1\subfolder\ функция записывает файл в
\\nsa\public\

У меня никогда не было такого поведения в Windows Vista или 7, но кажется, что MS ввела некоторые новые привилегии или ценные бумаги, которые вызывают такое поведение.

Я заметил, что многие люди жалуются на сопоставленные диски в Windows 8, особенно для процессов с повышенными правами, но все решения предлагают использовать пути UNC вместо буквы подключенного диска.

Я также заметил, что включение / отключение UAC не влияет на это.

Может кто-нибудь объяснить, как я могу достичь своей цели при копировании файла?

0

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]