问题
Objective : I am trying to send some files from my client to server. I am using "rsync" for transferring the data. I am using CreateProcess APi and passing the rsync path along with the parameters.
Positive Case: When i send data from local drives like "C:" is where my windows is installed the above method works properly and transfers data.
Problem : When i try to send data of a mapped drive (shared network drive) . The CreateProcess completes but the error which i get is rsync cannot find the file. The same rsync command , when i run on a command prompt all files are transferred successfully without any error but fails in transferring files with CreateProcess.
Code :
int CreateRsyncProcess(const wchar_t * ptrCommand)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
SECURITY_ATTRIBUTES sap,sat,sao;
HANDLE out;
DWORD pwExit;
//init the STARTUPINFO struct
memset(&si,0,sizeof(si));
si.cb=sizeof(si);
wstring cmd = L"";
cmd.append(ptrCommand);
//proc sec attributes
sap.nLength=sizeof(SECURITY_ATTRIBUTES);
sap.lpSecurityDescriptor= NULL;
sap.bInheritHandle=1;
//thread sec attributes
sat.nLength=sizeof(SECURITY_ATTRIBUTES);
sat.lpSecurityDescriptor= NULL;
sat.bInheritHandle=1;
//create the proc
if(!CreateProcess(NULL,(LPWSTR)cmd.c_str(),&sap,&sat,1,CREATE_NO_WINDOW,NULL,NULL,&si,&pi))
{
DWORD err = GetLastError();
if(out != INVALID_HANDLE_VALUE)
CloseHandle(out);
return 1;
}
//wait till the proc ends
WaitForSingleObject(pi.hProcess,INFINITE);
GetExitCodeProcess(pi.hProcess,&pwExit);
//close all
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
if(out != INVALID_HANDLE_VALUE)
CloseHandle(out);
TerminateProcess(pi.hProcess,0);
return pwExit;
}
Rsync Cmd : "C:\Program Files\cwRsync\bin\rsync.exe" -cvriHPDkREL --no-implied-dirs --stats -e '"C:\Program Files\cwRsync\bin\ssh" -o StrictHostKeyChecking=no -i "C:\Program Files\cwRsync\bin\rsync-key"' "/cygdrive/Z/64Bit" user@server.com:~/6a90c592-2b3b-4088-8942-2106776c863a/
Is it happening because of some security related issue or rights issue wit CreateProcess or some thing else? Please help as i am stuck on this.
Thanks
EDIT: : This is working fine as a normal process but when i run it in a service it fails. So basically the problem now is the service is not accessing the network shares. Any workarounds for that?
回答1:
Since apparently you are running a Service, you probably need to load the enviroment to have access to the mapped folders.
Something like this.
DWORD dwIdCurrentSession = 0xFFFFFFFF;
WTS_SESSION_INFO* pSessionInfo = NULL;
DWORD dwSessionsCount = 0;
if(WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSessionInfo, &dwSessionsCount))
{
for(int i=0; i<(int)dwSessionsCount; i++)
{
WTS_SESSION_INFO &si = pSessionInfo[i];
if(si.State == WTSActive)
{
dwIdCurrentSession = si.SessionId;
break;
}
}
WTSFreeMemory(pSessionInfo);
}
if(dwIdCurrentSession != 0xFFFFFFFF)
{
HANDLE hLoggedOnUserToken = NULL;
// Get Session User Token
if(WTSQueryUserToken(dwIdCurrentSession, &hLoggedOnUserToken))
{
LPVOID lpEnviroment = NULL;
if(CreateEnvironmentBlock(&lpEnviroment, hLoggedOnUserToken, false))
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
// Create Process
if(CreateProcessAsUser(hLoggedOnUserToken,
NULL,
(LPWSTR)cmd.c_str(),
NULL,
NULL,
FALSE,
CREATE_UNICODE_ENVIRONMENT,
lpEnviroment,
NULL,
&si,
&pi )
)
{
// Wait for finish......
// Clean up
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
}
DestroyEnvironmentBlock(lpEnviroment);
}
CloseHandle(hLoggedOnUserToken);
}
}
回答2:
Mapped drives are per session - services in an isolated session can't access mapped drives in user sessions. You'll need to map the drives in the service session, or use UNC paths (instead of mapped drive letters) and give the service users access to the share.
回答3:
What specific operating system, for example Windows 7 32-bit, Windows 7 64-bit, etc., are you using? Also, do you have UAC enabled? If you do have UAC enabled, does the problem go away when you run the application as an administrator.
Depending on what your answer to these questions are, I may be able to provide further assistance. I would have to do some research though.
At the moment, if UAC is indeed your problem, my only suggestion is that you investigate the possibility of using ShellExecuteEx instead. The RunElevated function found at Riding the Vista UAC elevator, up and down might be of use to you. For the sake of convenience I will include the function here.
BOOL RunElevated(
HWND hwnd, LPCTSTR pszPath,
LPCTSTR pszParameters = NULL, LPCTSTR pszDirectory = NULL)
{
SHELLEXECUTEINFO shex;
memset( &shex, 0, sizeof( shex) );
shex.cbSize = sizeof(SHELLEXECUTEINFO);
shex.fMask = 0;
shex.hwnd = hwnd;
shex.lpVerb = _T("runas");
shex.lpFile = pszPath;
shex.lpParameters = pszParameters;
shex.lpDirectory = pszDirectory;
shex.nShow = SW_NORMAL;
return ::ShellExecuteEx(&shex);
}
If using ShellExecuteEx is not an option, you can also try the CreateProcessElevated function found at Vista UAC: The Definitive Guide.
来源:https://stackoverflow.com/questions/21749854/security-issue-with-createprocess-api