C++ create process command line executing powershell command in command line arguments - c++

I want to create process with something like this:
LPTSTR cmdArgs = _T("C:\\Windows\\System32\\cmd.exe PowerShell -Command Add-AppxPackage -Path \"C:\\Users\\TEST2\\abc.appx\" ");
call the API as below:
CreateProcess(NULL, cmdArgs, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)
Here when I do so, application is goin into deadlock.

Related

Create Scheduled Task for a specific user

I'm trying to make a little application that I can use at my work for setting up PC and Laptop demos. This application will run a series of operations. One of these operations is to create a Scheduled Task for the Customer account. The Customer account is created simply via NET USER Customer /ADD /PASSWORDREQ:NO (I have tried using the Windows API to achieve this, but I ran into a lot of problems. But that is for another question).
The Scheduled Task that is created for the Customer account would be issued like so: SCHTASKS /CREATE /TN DemoReboot /SC DAILY /ST 12:00 /ET 18:00 /MO 2 /TR "SHUTDOWN /R /F /T 30".
I'm aware of the /U and /P parameters, but unfortunately they do not work as credentials aren't allowed to be saved on the machine, and if there is no password provided, you are prompted to enter a password.
My current approach of executing the command above is like so:
bool AccountManager::run(const QString &rUserName, const QString &rPass, const QString &rCommand)
{
HANDLE hToken;
LPVOID lpvEnv;
PROCESS_INFORMATION pi = {0};
STARTUPINFO si = {0};
si.cb = sizeof(STARTUPINFO);
std::wstring wUser = rUserName.toStdWString();
WCHAR *pUser = const_cast<WCHAR*>(wUser.c_str());
std::wstring wPass = rPass.toStdWString();
WCHAR *pPass = const_cast<WCHAR*>(wPass.c_str());
std::wstring wCommand = rCommand.toStdWString();
WCHAR *pCommand = const_cast<WCHAR*>(wCommand.c_str());
/*
if (!CreateProcessWithLogonW(test, L".", pass,
0, NULL, cmd,
CREATE_UNICODE_ENVIRONMENT, NULL, NULL,
&si, &pi))
DisplayError(str);
*/
if (!LogonUser(pUser, L".", pPass, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &hToken)) {
setLastError("LogonUser");
return false;
}
/*
if (!ImpersonateLoggedOnUser(&hToken))
{
setLastError("ImpersonateLoggedOnUser");
return false;
}
*/
if (!CreateEnvironmentBlock(&lpvEnv, hToken, TRUE)) {
setLastError("CreateEnvironmentBlock");
return false;
}
// I've tried specifying NULL for the second paramater (lpDomain)
if (!CreateProcessWithLogonW(pUser, L".", pPass,
LOGON_WITH_PROFILE, NULL, pCommand,
// I've tried using the created environmentBlock
//CREATE_UNICODE_ENVIRONMENT, lpvEnv, NULL,
CREATE_UNICODE_ENVIRONMENT, NULL, NULL,
&si, &pi)) {
setLastError("CreateProcessWithLogonW");
return false;
}
if (!DestroyEnvironmentBlock(lpvEnv)) {
setLastError("DestroyEnvironmentBlock");
return false;
}
CloseHandle(hToken);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
qDebug() << "finished";
return true;
}
The way this function is called:
void MainWindow::onCreateRebootTaskClicked()
{
// Memory Leak
QProcess *pProc = new QProcess();
pProc->setProgram("cmd.exe");
// Blank password is not allowed, so add temp one
pProc->setArguments({QString("/C net user %1 %2").arg(ui->cxNameLineEdit->text(), "cccx") });
pProc->start();
pProc->waitForFinished();
// Tried without using cmd /C
const QString command = QString("cmd /C SCHTASKS /CREATE /TN \"%1\" /SC DAILY /ST %2 /ET %3 /MO %4 /TR \"%5\"").arg(
ui->taskRebootNameLineEdit->text(),
ui->taskStartTimeEdit->text(),
ui->taskEndTimeEdit->text(),
ui->taskModifierSpinBox->text(),
QString("shutdown /r /f /t %1").arg(ui->taskRebootTimeOutSpinBox->value()));
if (!AccountManager::run(ui->cxNameLineEdit->text(), "cccx", command))
{
const auto &rError = AccountManager::getLastError();
QMessageBox::warning(this, rError.errorCodeName, rError.msg);
}
// Remove temp password
pProc->setArguments({QString("/C net user %1 %2").arg(ui->cxNameLineEdit->text(), "") });
pProc->start();
}
I have left some comments in the code stating some tweaks I have tried.
After the command is executed, I log onto the Customer account and run SCHTASKS /DELETE /TN DemoReboot to see if the Task was successfully created, but the task name isn't found.
Next I tried using the Run function listed above, specifying just cmd as the command so I can get the command line for the Customer account. With the command line that pops up, I manually enter SCHTASKS /CREATE /TN DemoReboot /SC DAILY /ST 12:00 /ET 18:00 /MO 2 /TR "SHUTDOWN /R /F /T 30", then sign into the Customer account and try to delete the Task again, which does work; the task is there to be deleted!
There are other ways I have thought about doing this, such as using the Registry for the Customer account, adding keys under RunOnce, but I have not been able to successfully access the Registry of the Customer account from a different local account.
Hopefully I didn't leave anything out.
Update:
I have managed to figure out what the issue is. The first issue is that for the /MO Option, the taskModifierSpinBox has "hr" suffixed to the text. To fix that, I just split the QString like so: ui->taskModifierSpinBox.text().split(' ').first() What I should have done which I didn't think of just until now is use ui->taskModiferSpinBox->value().toString();
The other issue is the escaped double quotes... I don't really need them around the argument for /TN, but for /TR I do. I have tried using single quotes which did not work. I have tried doubling up on the double quotes, and that didn't work either. I also tried \\\" but that didn't work either.
What I have resulted to is to create a batch file, and pass the batch file as the command to run. Now that isn't really ideal, but I haven't figured out a way to successfully pass an argument that has spaces to /TR

how to open partition with CreateFile API?

I want to get handle from drive C:/.I can get handle from disk by:
HANDLE hd = CreateFile("\\\\.\\PhysicalDrive0", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, 0, NULL);
how to access partition of disk?
when use this code:
HANDLE hd = CreateFile("\\.\C", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, 0, NULL);
and use GetLastError() error code is 123.
ERROR_INVALID_NAME
123 (0x7B)
The filename, directory name, or volume label syntax is incorrect.
from Microsoft doc:
image
but not work!
thanks in advance.
The name you should be using to open a volume is C: and make sure the back slashes are escaped appropriately.
HANDLE hd = CreateFile("\\\\.\\C:", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, 0, NULL);
Note that you will probably get error 5 (Access denied), unless the exe is being run with administrator privileges.

CreateNamedPipe causes ERROR_ACCESS_DENIED?

i need to create a named pipe for communication between client and server (in same host), here is the code:
WCHAR wszPipeName[MAX_FILE_LENGTH];
swprintf_s(wszPipeName, MAX_FILE_LENGTH, L"\\\\.\\pipe\\TEST%d", uniqueID);
pipe = CreateNamedPipe(
wszPipeName, // name of the pipe
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_NOWAIT,
1,
MAX_MSG_SIZE,
MAX_MSG_SIZE , //inbound buffer
MAX_READ_DATA_TIMEOUT,
NULL // use default security attributes
);
It the handler get back is always INVALID_HANDLE_VAULE, and the error is ERROR_ACCESS_DENIED.
Is there anything wrong here? It is running on Windows 7/8.
Thanks
This is Python code, but this sets up a security descriptor for the local user and denies remote:
dacl = ACL()
# Deny NT AUTHORITY\NETWORK SID
sid = CreateWellKnownSid(WinNetworkSid)
dacl.AddAccessDeniedAce(ACL_REVISION, GENERIC_ALL, sid)
# Allow current user SID
token = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY)
sid = GetTokenInformation(token, TokenUser)[0]
dacl.AddAccessAllowedAce(ACL_REVISION, GENERIC_READ | GENERIC_WRITE, sid)
security_descriptor = SECURITY_DESCRIPTOR()
security_descriptor.SetSecurityDescriptorDacl(True, dacl, False)
security_attributes = SECURITY_ATTRIBUTES()
security_attributes.SECURITY_DESCRIPTOR = security_descriptor
pipe = CreateNamedPipe(
<your other params here>
security_attributes
)
Found the reason, it is because the security limitation. After providing a suitable security descriptor, it just works!

cmd command in wince7

I'm trying to run a cmd command in my wince7 machine.
my code is: (for example)
STARTUPINFOW siStartupInfo;
PROCESS_INFORMATION piProcessInfo;
memset(&siStartupInfo, 0, sizeof(siStartupInfo));
memset(&piProcessInfo, 0, sizeof(piProcessInfo));
siStartupInfo.cb = sizeof(siStartupInfo);
TCHAR regsvrActiveXConsole[256] = L"cd";
if (CreateProcess(L"\\Windows\\cmd.exe", regsvrActiveXConsole ,0,0,false,NULL,0,0,&siStartupInfo, &piProcessInfo))
{
}
else
{
}
and I get: "unrecognized option cd."
Do I miss something?
Do I need to add something to the image in order to run cmd commands?
cmd has certain usage rules, it doesn't just execute whatever you pass in arguments, type cmd /? in command prompt for more information. To make it execute a command, you need the /C option. The valid invocation would be:
cmd /C cd
i.e.
TCHAR regsvrActiveXConsole[256] = L"/C cd";

Cannot upload a file to a ftp server using C++

I have this simple code to upload a file to a server, but it seems that it doesnt work, doesn't upload any file(FtpPutFile returns 0). I am using FileZilla Server and this is my code and what FileZilla says:
void upload()
{
hInternet = InternetOpen(NULL, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
hFtpSession = InternetConnect(hInternet,"127.0.0.1",INTERNET_DEFAULT_FTP_PORT,"vbx","pass",INTERNET_SERVICE_FTP, 0,0 );
FtpPutFile(hFtpSession, "c:\\stories.txt", "e:\\text.txt", FTP_TRANSFER_TYPE_BINARY, 0);
InternetCloseHandle(hFtpSession);
InternetCloseHandle(hInternet);
}
(000011)3/27/2011 0:01:53 AM - (not logged in) (127.0.0.1)> USER vbx
(000011)3/27/2011 0:01:53 AM - (not logged in) (127.0.0.1)> 331 Password required for vbx
(000011)3/27/2011 0:01:53 AM - (not logged in) (127.0.0.1)> PASS *******
(000011)3/27/2011 0:01:53 AM - vbx (127.0.0.1)> 230 Logged on
(000011)3/27/2011 0:01:53 AM - vbx (127.0.0.1)> disconnected.
Thank you.
edit: GetLastError() returns: The process cannot access the file because it is being used by another process.
With GetLastError() returning ERROR_SHARING_VIOLATION (32) for FtpPutFile, it likely means that that there is an open handle to "c:\stories.txt" that prevents read sharing. If you have this file open in your program, you will need to either allow read sharing in the CreateFile call or close all open handles that prevent sharing so that FtpPutFile can open the file.