security issue with CreateProcess API - c++

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?

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.

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);
}
}

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.

Related

Logoff remote system using c++

I am looking for an API to logoff current user on remote computer. Two
functions ExitWindows and InitiateSystemShutdown seem not exactly what I
want. The first one doesn't accept computer name, the second one doesn't
have logoff option.is it possible to logoff current user
on remote computer ?. Can someone tell me how to achieve this in a
C++ program?
I knew that you want to shutdown system by using exitwindows function.
However, if you want to shut down the remote system in your own process, you need to use the exitwindowsEX function and write a program that specifies the process ID.
The relevant function references are as follows:
https://learn.microsoft.com/zh-cn/windows/win32/shutdown/how-to-shut-down-the-system
The following are specific codes:
#pragma region
#include<windows.h>
#pragma warning(disable:4996)
BOOL ReSetWindows(DWORD dwFlags, BOOL bForce)
{
if (dwFlags != EWX_LOGOFF && dwFlags != EWX_REBOOT && dwFlags != EWX_SHUTDOWN)
return FALSE;
OSVERSIONINFO osvi = { 0 };
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (!GetVersionEx(&osvi))
{
return FALSE;
}
if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
{
//EnableShutDownPriv();
}
dwFlags |= (bForce != FALSE) ? EWX_FORCE : EWX_FORCEIFHUNG;
return ExitWindowsEx(dwFlags, 0);
}
int main()
{
ReSetWindows(EWX_LOGOFF, false);//logoff
//ReSetWindows(EWX_REBOOT, true);//restart
//ReSetWindows(EWX_SHUTDOWN, true);//shutdown
}
=======================
Caution!!!Please save your important file before running or running in the virtual machine
WTSLogoffSession? but the concept of a current user on a remote machine does not really exist, you would have to inspect the sessions with WTSEnumerateSessions+WTSQuerySessionInformation if you want to find a specific user. This only makes sense in a environment where there is a NT domain so you can match against a domain SID. Without a domain, all you can do is match against the username which might be enough for you.
This is the program specifies the process ID:
DWORD GetProcessIDByName(LPCTSTR szProcessName)
{
STARTUPINFO st;
PROCESS_INFORMATION pi;
PROCESSENTRY32 ps;
HANDLE hSnapshot;
DWORD dwPID = 0;
ZeroMemory(&st, sizeof(STARTUPINFO));
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
st.cb = sizeof(STARTUPINFO);
ZeroMemory(&ps, sizeof(PROCESSENTRY32));
ps.dwSize = sizeof(PROCESSENTRY32);
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapshot == INVALID_HANDLE_VALUE)//
{
return dwPID;
}
if (!Process32First(hSnapshot, &ps))
{
return dwPID;
}
do
{
if (lstrcmpi(ps.szExeFile, szProcessName) == 0)
{
dwPID = ps.th32ProcessID;
}
} while (Process32Next(hSnapshot, &ps));
CloseHandle(hSnapshot);
return dwPID;//
}
You need this line of code in your main function:
DWORD pId = GetProcessIDByName("\\\.exe");
Closing remote system by local machine is easy. Closing local machine by remote machine sounds like a virus. No offense, it is difficult to implement. Maybe you can try using socket to communicate local machine with virtual machine.

In C++ Trying to Run an EXE from a UNC in Windows 10. Very new to C++

I just started writing a console app in C++. It does some verification and then it needs to find and run an executable that can be in a variety of places depending on how it was deployed. So most of the script works and even the run part works depending on the OS and location. If it is local it works and if it is windows 7 it seems to work even on the UNC. But in Windows 10 it just exits out.
The script finds the exe and runs it from the path it is in. It works when I created the application as a batch file the uses popD to move to the exe location for working directory but I can't seem to mimic that functionality in C++. I have tried SetCurrentDirectory but it won't take my string that I am trying to pass.
if (version >= minver)
{
std::string name = "testApp.exe";
std::string path = (fs::current_path().string());
for (const auto& entry : fs::recursive_directory_iterator(path))
{
std::string list = entry.path().string();
int found;
if ((found = list.find(name)) !=list.npos)
{
std::cout << list << std::endl;
\\This is the part that sometimes works and sometimes doesn't
system(list.c_str());
}
}
}
As you can start your program from console, try to use CreateProcess function in console mode:
int runProcessFromCmd( char* pcExecPath)
{
if( NULL == pcExecPath)
{
printf("empty path!");
return -1;
}
STARTUPINFO si;
PROCESS_INFORMATION pi;
memset( &si, 0, sizeof(si) );
memset( &pi, 0, sizeof(pi) );
si.cb = sizeof(si);
// Start child process from command line
// First parameter = NULL => we use cmd
if( !CreateProcess( NULL, pcExecPath, NULL,NULL, FALSE, 0, NULL, NULL, &si, &pi ))
{
printf( "CreateProcess failed with error (%d).\n", GetLastError() );
return -2;
}
// Wait child process
WaitForSingleObject( pi.hProcess, INFINITE );
// Close all handles
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
}
So in the long run I was chasing down the problem in the wrong way. Thanks to LandStalker for putting on a better path. I was right about mimicking a popD but had a hard time doing it in the right way to actually work.
I SetCurrentDirectory and then did a ShellExecute on the program name.

CreateProcess calling cmd.exe incl. arguments with no showing (flashing) window?

The saga continues...
I've searched the web, i've searched on StackOverflow, i found many hope giving answers/solutions, but somehow they have all failed (up)on me (including the ones related to ShellExecute(Ex) ).
How to hide a (flashing) CMD window (incl. arguments) using CreateProcess??
I basically want to call/execute a set of conditional/native cmd.exe commands (i.e. FOR /F, and ||), but also an external command FIND(STR).exe. And this, without showing a (flashing) CMD window.
But even hiding something as simple as "cmd.exe /C ECHO ...flashing window is bad..." seems impossible to do.
The code i've tried (including many variations related to the dwFlags and wShowWindow flags
#include <windows.h>
int main()
{
char cmdline[] = "cmd.exe /c ECHO ...flashing window is bad...";
PROCESS_INFORMATION pi;
STARTUPINFO si;
// memset(&si,0,sizeof(STARTUPINFO));
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
// si.dwFlags = STARTF_USESTDHANDLES;
// si.dwFlags = CREATE_NO_WINDOW;
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
// si.wShowWindow = CREATE_NO_WINDOW;
CreateProcess(NULL, (LPSTR) cmdline, NULL, NULL, 0, 0, NULL, NULL, &si, &pi);
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
// ExitProcess;
return 0;
}
I don't want to rely on external programs i.e. .vbs (Windows Scripting Host) or shortcut tricks, but simply a standalone compiled .exe.
Is this (really) too much to ask, or am i doing it (completely) wrong?
Thanks...
Update: You also seem to confuse CreateProcess flags (its dwCreationFlags argument) with the member of STARTUPINFO structure. These are different flags, CREATE_NO_WINDOW should not be in STARTUPINFO.
You have to pass the CREATE_NO_WINDOW flag, then the console window won't show. Originally I've answered that you have to redirect the standard handles which is not correct (but still highly recommanded).
Set STARTF_USESTDHANDLES and fill in appropriate handles. If you are interested in the output of the process, create pipes, otherwise you can just open nul an pass that.
Try Using ProcessBuilder. Here is an example of some code that I have that seems to work just fine. In my code below, the shellScript is a StringBuilder that I am dynamically creating that contains the command and it's parameters that I want to execute.
String[] scriptArray = shellScript.toString().split(" ");
ProcessBuilder builder = new ProcessBuilder(scriptArray);
File outputFile = new File("/logs/AgentOutputLog.txt");
File errorFile = new File("/logs/AgentErrorLog.txt");
builder.redirectOutput(outputFile);
builder.redirectError(errorFile);
Process process = builder.start();
int errCode = process.waitFor();
//errCode = 0 means online
if(errCode == 0){
success = true;
break;
//errCode = 1 means offline
} else if (errCode == 1){
success = false;
break;
}

windows service start a interactive process(MFC application) on Windows XP

now I have a windows service, and I want the service create a GUI process(MFC application). And I referenced the code:Launch your application in Vista under the local system account without the UAC popup .
And the important is :
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();
WTSQueryUserToken(dwSessionId,&hUserToken);
dwCreationFlags = NORMAL_PRIORITY_CLASS|CREATE_NEW_CONSOLE;
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb= sizeof(STARTUPINFO);
si.lpDesktop = "winsta0\\default";
ZeroMemory(&pi, sizeof(pi));
TOKEN_PRIVILEGES tp;
LUID luid;
hProcess = OpenProcess(MAXIMUM_ALLOWED,FALSE,GetCurrentProcessId();
if(!::OpenProcessToken(hProcess,TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY
|TOKEN_DUPLICATE|TOKEN_ASSIGN_PRIMARY|TOKEN_ADJUST_SESSIONID
|TOKEN_READ|TOKEN_WRITE,&hPToken))
{
int abcd = GetLastError();
printf("Process token open Error: %u\n",GetLastError());
}
if (!LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&luid))
{
printf("Lookup Privilege value Error: %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);
int dup = GetLastError();
//Adjust Token privilege
SetTokenInformation(hUserTokenDup,TokenSessionId,(void*)dwSessionId,sizeof(DWORD));
if (!AdjustTokenPrivileges(hUserTokenDup,FALSE,&tp,sizeof(TOKEN_PRIVILEGES),(PTOKEN_PRIVILEGES)NULL,NULL))
{
int abc =GetLastError();
printf("Adjust Privilege value Error: %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;
// Launch the process in the client's logon session.
bResult = CreateProcessAsUser(
hUserTokenDup, // client's access token
_T("TestDialog.exe"), // 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
);
// End impersonation of client.
//GetLastError Shud be 0
int iResultOfCreateProcessAsUser = GetLastError();
//Perform All the Close Handles task
CloseHandle(hProcess);
CloseHandle(hUserToken);
CloseHandle(hUserTokenDup);
CloseHandle(hPToken);
return 0;
Now the MFC application can be started after the service stared, it works well. And the process user name is System.
But when I logoff my account(the GUI application is running while click the windows system logoff button), the MFC application have a VC++ crash, the crash point the MFC internal function afxactivationwndproc .
My MFC application is just created by the VS2010 IDE without modify.
My test environment is on Windows XP.
If I double click the application to run it, and logoff with the application running, no error occurs.
So I want to know:
When user logoff, will system force kill my MFC application process? (Note: The process user name is System)
As mentioned, if I double click the application to run it, it is OK. So is there any problem with the service starting method? Or we should add addition necessary operation to the MFC application.
Is there any other possible reason for this error?
Thank you very much!

TerminateProcess not suceeding on Windows 10

Our C++ app launches a separate .exe ( which may start its own sub-processes) using CreateProcess as below.
BOOL started = ::CreateProcess(NULL, // application
p, // parameters
NULL, // process security
NULL, // thread security
TRUE, // inherit handles flag
0, // flags
NULL, // inherit environment
dirLP, // inherit directory
&startup, // STARTUPINFO
&procinfo); // PROCESS_INFORMATIO
In case we need cancel the "job" we use CreateToolhelp32Snapshot to iterate through the process list to find any child processes of the one we launched.
static BOOL TerminateProcessTree (HANDLE parentProcess,UINT exitCode)
{
BOOL result=TRUE;
HANDLE hProcessSnap = NULL;
PROCESSENTRY32 pe32 = {0};
// Take a snapshot of all processes in the system.
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE)
return (FALSE);
pe32.dwSize = sizeof(PROCESSENTRY32);
// Walk the snapshot of the processes
DWORD parentID=GetProcessId(parentProcess);
if(parentID==0){
PrintLastError("GetProcessId");
return FALSE;
}
if (Process32First(hProcessSnap, &pe32)) {
do{
if(pe32.th32ParentProcessID==parentID){
HANDLE hProcess = OpenProcess (PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION, FALSE, pe32.th32ProcessID);
if(hProcess!=NULL){
BOOL terminateChildren=TerminateProcessTree(hProcess,exitCode);
BOOL terminatedChild = TerminateProcess(hProcess, exitCode);
if (!terminatedChild){
PrintLastError("TerminateProcess");
}
CloseHandle(hProcess);
if(!terminatedChild || !terminateChildren){
result=FALSE;
break;
}
} else{
PrintLastError("OpenProcess");
}
}
}while (Process32Next(hProcessSnap, &pe32));
}
CloseHandle (hProcessSnap);
DWORD checkCode=0;
BOOL terminated;
if(GetExitCodeProcess(parentProcess,&checkCode) && checkCode==STILL_ACTIVE){
terminated=TerminateProcess(parentProcess,exitCode);
if (!terminated){
PrintLastError("TerminateProcess");
result= FALSE;
}
}
return result;
}
As noted, this works fine on Windows 7. Windows 10 fails with "Access Denied" on the first call "TerminateProcess". Clearly something has changed in the Windows security model when it comes to processes.
The robust way to deal with controlling a process tree of objects is to use Job objects as noted in the comment threads.
The one thing to keep in mind is that a process can only belong to a single job, and by default any EXE that the OS determines needs appcompat help is put into a job object automatically managed by the "Program Compatibility Assistant". This makes using a Job object to manage arbitrary 3rd party EXEs a little bit more complicated (i.e. AssignProcessToJobObject fails for these processes).
If you are using CreateProcess you can make use of the flag CREATE_BREAKAWAY_FROM_JOB. See this blog post. This works fine as long as the target EXE has the same rights as the calling object.
For a Standard User EXE to run an EXE that might need Administrator rights (i.e. they contain a manifest which marks it as requireAdministrator), you have to use ShellExecute or ShellExecuteEx as calling CreateProcess in this case will fail. If your target EXEs are all using the proper manifest elements then it won't be put into a PCA Job object.. You can use the trick of passing SEE_MASK_FLAG_NO_UI which will have the side-effect of avoiding the PCA job behavior. If you are launching arbitrary 3rd party EXEs, you should use ShellExecuteEx and not CreateProcess.
bool SpawnProcess( const WCHAR* szExePath, const WCHAR* szExeArgs )
{
if( !szExePath )
return false;
// NOTE: szExeArgs can be nullptr.
// Get working directory from executable path.
WCHAR szDirectory[MAX_PATH] = {0};
wcscpy_s( szDirectory, szExePath );
PathRemoveFileSpec( szDirectory );
// ShellExecute or ShellExecuteEx must be used instead of CreateProcess
// to permit the shell to display a UAC prompt asking for consent to
// elevate when the target executable's manifest specifies a run level
// of "requireAdministrator".
//
// You can only use CreateProcess if you know that the application you
// are spawning will be at the same run level as the current process.
// Otherwise, you will receive ERROR_ACCESS_DENIED if the elevation
// consent could not be obtained.
SHELLEXECUTEINFO info = {};
info.cbSize = sizeof( info );
info.lpVerb = L"open";
info.fMask = SEE_MASK_FLAG_NO_UI;
info.lpFile = szExePath;
info.lpParameters = szExeArgs;
info.lpDirectory = szDirectory;
info.nShow = SW_SHOW;
if( !ShellExecuteEx( &info ) )
return false;
return true;
}
Note that if you want to wait until this process exits, you can use:
bool SpawnProcessAndWait( const WCHAR *szExePath, const WCHAR *szExeArgs, DWORD *pdwExitCode )
{
if( !szExePath )
return false;
// NOTE: szExeArgs and pExitCode can be nullptr.
// Get working directory from executable path.
WCHAR szDirectory[MAX_PATH] = {0};
wcscpy_s( szDirectory, szExePath );
PathRemoveFileSpec( szDirectory );
// See SpawnProcess for information why ShellExecute or ShellExecuteEx
// must be used instead of CreateProcess.
SHELLEXECUTEINFO info = {};
info.cbSize = sizeof( info );
info.lpVerb = L"open";
info.fMask = SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC | SEE_MASK_NOCLOSEPROCESS;
info.lpFile = szExePath;
info.lpParameters = szExeArgs;
info.lpDirectory = szDirectory;
info.nShow = SW_SHOW;
if( !ShellExecuteEx( &info ) )
return false;
// Wait for process to finish.
WaitForSingleObject( info.hProcess, INFINITE );
// Return exit code from process, if requested by caller.
if( pdwExitCode )
GetExitCodeProcess( info.hProcess, pdwExitCode );
CloseHandle( info.hProcess );
return true;
}
You haven't noted if your "master" application here is using administrator or Standard User rights. Ideally it is using Standard User rights per the User Account Control guidelines dating back to Windows Vista. If your app is running as Standard User, then it's likely that your code no longer works due to security improvements to keep non-Administrator malware from doing this kind of thing to other processes.
For general appcompat questions about Windows 10, be sure to read the Windows and Windows Server compatibility cookbook and look back at the Windows 8.0 and Windows 8.1 material if you are jumping directly from Windows 7 to Windows 10.