mirror of
https://github.com/reactos/reactos.git
synced 2025-08-06 23:13:04 +00:00
Allow launching of console apps from GUI apps
svn path=/trunk/; revision=7107
This commit is contained in:
parent
41b4cb6b5a
commit
78aaee0a8b
8 changed files with 166 additions and 76 deletions
|
@ -32,6 +32,7 @@ typedef struct
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
HANDLE Console;
|
||||||
HANDLE InputHandle;
|
HANDLE InputHandle;
|
||||||
HANDLE OutputHandle;
|
HANDLE OutputHandle;
|
||||||
} CSRSS_CREATE_PROCESS_REPLY, *PCSRSS_CREATE_PROCESS_REPLY;
|
} CSRSS_CREATE_PROCESS_REPLY, *PCSRSS_CREATE_PROCESS_REPLY;
|
||||||
|
@ -77,6 +78,7 @@ typedef struct
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
HANDLE Console;
|
||||||
HANDLE InputHandle;
|
HANDLE InputHandle;
|
||||||
HANDLE OutputHandle;
|
HANDLE OutputHandle;
|
||||||
} CSRSS_ALLOC_CONSOLE_REPLY, *PCSRSS_ALLOC_CONSOLE_REPLY;
|
} CSRSS_ALLOC_CONSOLE_REPLY, *PCSRSS_ALLOC_CONSOLE_REPLY;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: console.c,v 1.70 2003/12/02 11:38:46 gvg Exp $
|
/* $Id: console.c,v 1.71 2003/12/18 09:51:08 gvg Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS system libraries
|
* PROJECT: ReactOS system libraries
|
||||||
|
@ -1253,6 +1253,7 @@ WINBOOL STDCALL AllocConsole(VOID)
|
||||||
SetLastErrorByStatus ( Status );
|
SetLastErrorByStatus ( Status );
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
NtCurrentPeb()->ProcessParameters->hConsole = Reply.Data.AllocConsoleReply.Console;
|
||||||
SetStdHandle( STD_INPUT_HANDLE, Reply.Data.AllocConsoleReply.InputHandle );
|
SetStdHandle( STD_INPUT_HANDLE, Reply.Data.AllocConsoleReply.InputHandle );
|
||||||
SetStdHandle( STD_OUTPUT_HANDLE, Reply.Data.AllocConsoleReply.OutputHandle );
|
SetStdHandle( STD_OUTPUT_HANDLE, Reply.Data.AllocConsoleReply.OutputHandle );
|
||||||
hStdError = DuplicateConsoleHandle(Reply.Data.AllocConsoleReply.OutputHandle,
|
hStdError = DuplicateConsoleHandle(Reply.Data.AllocConsoleReply.OutputHandle,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: create.c,v 1.72 2003/10/31 16:27:01 navaraf Exp $
|
/* $Id: create.c,v 1.73 2003/12/18 09:51:08 gvg Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS system libraries
|
* PROJECT: ReactOS system libraries
|
||||||
|
@ -712,6 +712,8 @@ CreateProcessW
|
||||||
WCHAR TempCommandLineNameW[256];
|
WCHAR TempCommandLineNameW[256];
|
||||||
UNICODE_STRING RuntimeInfo_U;
|
UNICODE_STRING RuntimeInfo_U;
|
||||||
PVOID ImageBaseAddress;
|
PVOID ImageBaseAddress;
|
||||||
|
BOOL InputSet, OutputSet, ErrorSet;
|
||||||
|
BOOL InputDup, OutputDup, ErrorDup;
|
||||||
|
|
||||||
DPRINT("CreateProcessW(lpApplicationName '%S', lpCommandLine '%S')\n",
|
DPRINT("CreateProcessW(lpApplicationName '%S', lpCommandLine '%S')\n",
|
||||||
lpApplicationName, lpCommandLine);
|
lpApplicationName, lpCommandLine);
|
||||||
|
@ -1044,11 +1046,18 @@ CreateProcessW
|
||||||
CsrRequest.Data.CreateProcessRequest.NewProcessId =
|
CsrRequest.Data.CreateProcessRequest.NewProcessId =
|
||||||
ProcessBasicInfo.UniqueProcessId;
|
ProcessBasicInfo.UniqueProcessId;
|
||||||
if (Sii.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI)
|
if (Sii.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI)
|
||||||
{
|
{
|
||||||
/* Do not create a console for GUI applications */
|
/* Do not create a console for GUI applications */
|
||||||
dwCreationFlags &= ~CREATE_NEW_CONSOLE;
|
dwCreationFlags &= ~CREATE_NEW_CONSOLE;
|
||||||
dwCreationFlags |= DETACHED_PROCESS;
|
dwCreationFlags |= DETACHED_PROCESS;
|
||||||
}
|
}
|
||||||
|
else if (Sii.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI)
|
||||||
|
{
|
||||||
|
if (NULL == Ppb->hConsole)
|
||||||
|
{
|
||||||
|
dwCreationFlags |= CREATE_NEW_CONSOLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
CsrRequest.Data.CreateProcessRequest.Flags = dwCreationFlags;
|
CsrRequest.Data.CreateProcessRequest.Flags = dwCreationFlags;
|
||||||
CsrRequest.Data.CreateProcessRequest.CtrlDispatcher = ConsoleControlDispatcher;
|
CsrRequest.Data.CreateProcessRequest.CtrlDispatcher = ConsoleControlDispatcher;
|
||||||
Status = CsrClientCallServer(&CsrRequest,
|
Status = CsrClientCallServer(&CsrRequest,
|
||||||
|
@ -1059,92 +1068,163 @@ CreateProcessW
|
||||||
{
|
{
|
||||||
DbgPrint("Failed to tell csrss about new process. Expect trouble.\n");
|
DbgPrint("Failed to tell csrss about new process. Expect trouble.\n");
|
||||||
}
|
}
|
||||||
|
else if (Sii.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI)
|
||||||
|
{
|
||||||
|
Ppb->hConsole = CsrReply.Data.CreateProcessReply.Console;
|
||||||
|
}
|
||||||
|
|
||||||
// Set the child console handles
|
InputSet = FALSE;
|
||||||
Ppb->hStdInput = NtCurrentPeb()->ProcessParameters->hStdInput;
|
OutputSet = FALSE;
|
||||||
Ppb->hStdOutput = NtCurrentPeb()->ProcessParameters->hStdOutput;
|
ErrorSet = FALSE;
|
||||||
Ppb->hStdError = NtCurrentPeb()->ProcessParameters->hStdError;
|
|
||||||
|
|
||||||
|
/* Set the child console handles */
|
||||||
|
|
||||||
|
/* First check if handles were passed in startup info */
|
||||||
if (lpStartupInfo && (lpStartupInfo->dwFlags & STARTF_USESTDHANDLES))
|
if (lpStartupInfo && (lpStartupInfo->dwFlags & STARTF_USESTDHANDLES))
|
||||||
{
|
{
|
||||||
if (lpStartupInfo->hStdInput)
|
if (lpStartupInfo->hStdInput)
|
||||||
|
{
|
||||||
Ppb->hStdInput = lpStartupInfo->hStdInput;
|
Ppb->hStdInput = lpStartupInfo->hStdInput;
|
||||||
|
InputSet = TRUE;
|
||||||
|
InputDup = TRUE;
|
||||||
|
}
|
||||||
if (lpStartupInfo->hStdOutput)
|
if (lpStartupInfo->hStdOutput)
|
||||||
|
{
|
||||||
Ppb->hStdOutput = lpStartupInfo->hStdOutput;
|
Ppb->hStdOutput = lpStartupInfo->hStdOutput;
|
||||||
|
OutputSet = TRUE;
|
||||||
|
OutputDup = TRUE;
|
||||||
|
}
|
||||||
if (lpStartupInfo->hStdError)
|
if (lpStartupInfo->hStdError)
|
||||||
|
{
|
||||||
Ppb->hStdError = lpStartupInfo->hStdError;
|
Ppb->hStdError = lpStartupInfo->hStdError;
|
||||||
}
|
ErrorSet = TRUE;
|
||||||
|
ErrorDup = TRUE;
|
||||||
if (IsConsoleHandle(Ppb->hStdInput))
|
|
||||||
{
|
|
||||||
Ppb->hStdInput = CsrReply.Data.CreateProcessReply.InputHandle;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DPRINT("Duplicate input handle\n");
|
|
||||||
Status = NtDuplicateObject (NtCurrentProcess(),
|
|
||||||
Ppb->hStdInput,
|
|
||||||
hProcess,
|
|
||||||
&Ppb->hStdInput,
|
|
||||||
0,
|
|
||||||
TRUE,
|
|
||||||
DUPLICATE_SAME_ACCESS);
|
|
||||||
if(!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT("NtDuplicateObject failed, status %x\n", Status);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsConsoleHandle(Ppb->hStdOutput))
|
/* Check if new console was created, use it for input and output if
|
||||||
|
not overridden */
|
||||||
|
if (0 != (dwCreationFlags & CREATE_NEW_CONSOLE)
|
||||||
|
&& NT_SUCCESS(Status) && NT_SUCCESS(CsrReply.Status))
|
||||||
{
|
{
|
||||||
Ppb->hStdOutput = CsrReply.Data.CreateProcessReply.OutputHandle;
|
if (! InputSet)
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DPRINT("Duplicate output handle\n");
|
|
||||||
Status = NtDuplicateObject (NtCurrentProcess(),
|
|
||||||
Ppb->hStdOutput,
|
|
||||||
hProcess,
|
|
||||||
&Ppb->hStdOutput,
|
|
||||||
0,
|
|
||||||
TRUE,
|
|
||||||
DUPLICATE_SAME_ACCESS);
|
|
||||||
if(!NT_SUCCESS(Status))
|
|
||||||
{
|
{
|
||||||
DPRINT("NtDuplicateObject failed, status %x\n", Status);
|
Ppb->hStdInput = CsrReply.Data.CreateProcessReply.InputHandle;
|
||||||
|
InputSet = TRUE;
|
||||||
|
InputDup = FALSE;
|
||||||
|
}
|
||||||
|
if (! OutputSet)
|
||||||
|
{
|
||||||
|
Ppb->hStdOutput = CsrReply.Data.CreateProcessReply.OutputHandle;
|
||||||
|
OutputSet = TRUE;
|
||||||
|
OutputDup = FALSE;
|
||||||
|
}
|
||||||
|
if (! ErrorSet)
|
||||||
|
{
|
||||||
|
Ppb->hStdError = CsrReply.Data.CreateProcessReply.OutputHandle;
|
||||||
|
ErrorSet = TRUE;
|
||||||
|
ErrorDup = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (IsConsoleHandle(Ppb->hStdError))
|
|
||||||
|
/* Use existing handles otherwise */
|
||||||
|
if (! InputSet)
|
||||||
{
|
{
|
||||||
CsrRequest.Type = CSRSS_DUPLICATE_HANDLE;
|
Ppb->hStdInput = NtCurrentPeb()->ProcessParameters->hStdInput;
|
||||||
CsrRequest.Data.DuplicateHandleRequest.ProcessId = ProcessBasicInfo.UniqueProcessId;
|
InputDup = TRUE;
|
||||||
CsrRequest.Data.DuplicateHandleRequest.Handle = CsrReply.Data.CreateProcessReply.OutputHandle;
|
}
|
||||||
Status = CsrClientCallServer(&CsrRequest,
|
if (! OutputSet)
|
||||||
&CsrReply,
|
{
|
||||||
sizeof(CSRSS_API_REQUEST),
|
Ppb->hStdOutput = NtCurrentPeb()->ProcessParameters->hStdOutput;
|
||||||
sizeof(CSRSS_API_REPLY));
|
OutputDup = TRUE;
|
||||||
if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrReply.Status))
|
}
|
||||||
|
if (! ErrorSet)
|
||||||
|
{
|
||||||
|
Ppb->hStdError = NtCurrentPeb()->ProcessParameters->hStdError;
|
||||||
|
ErrorDup = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now duplicate handles if required */
|
||||||
|
if (InputDup)
|
||||||
|
{
|
||||||
|
if (IsConsoleHandle(Ppb->hStdInput))
|
||||||
{
|
{
|
||||||
Ppb->hStdError = INVALID_HANDLE_VALUE;
|
Ppb->hStdInput = CsrReply.Data.CreateProcessReply.InputHandle;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Ppb->hStdError = CsrReply.Data.DuplicateHandleReply.Handle;
|
DPRINT("Duplicate input handle\n");
|
||||||
|
Status = NtDuplicateObject (NtCurrentProcess(),
|
||||||
|
Ppb->hStdInput,
|
||||||
|
hProcess,
|
||||||
|
&Ppb->hStdInput,
|
||||||
|
0,
|
||||||
|
TRUE,
|
||||||
|
DUPLICATE_SAME_ACCESS);
|
||||||
|
if(!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("NtDuplicateObject failed, status %x\n", Status);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if (OutputDup)
|
||||||
{
|
{
|
||||||
DPRINT("Duplicate error handle\n");
|
if (IsConsoleHandle(Ppb->hStdOutput))
|
||||||
Status = NtDuplicateObject (NtCurrentProcess(),
|
|
||||||
Ppb->hStdError,
|
|
||||||
hProcess,
|
|
||||||
&Ppb->hStdError,
|
|
||||||
0,
|
|
||||||
TRUE,
|
|
||||||
DUPLICATE_SAME_ACCESS);
|
|
||||||
if(!NT_SUCCESS(Status))
|
|
||||||
{
|
{
|
||||||
DPRINT("NtDuplicateObject failed, status %x\n", Status);
|
Ppb->hStdOutput = CsrReply.Data.CreateProcessReply.OutputHandle;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DPRINT("Duplicate output handle\n");
|
||||||
|
Status = NtDuplicateObject (NtCurrentProcess(),
|
||||||
|
Ppb->hStdOutput,
|
||||||
|
hProcess,
|
||||||
|
&Ppb->hStdOutput,
|
||||||
|
0,
|
||||||
|
TRUE,
|
||||||
|
DUPLICATE_SAME_ACCESS);
|
||||||
|
if(!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("NtDuplicateObject failed, status %x\n", Status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ErrorDup)
|
||||||
|
{
|
||||||
|
if (IsConsoleHandle(Ppb->hStdError))
|
||||||
|
{
|
||||||
|
CsrRequest.Type = CSRSS_DUPLICATE_HANDLE;
|
||||||
|
CsrRequest.Data.DuplicateHandleRequest.ProcessId = ProcessBasicInfo.UniqueProcessId;
|
||||||
|
CsrRequest.Data.DuplicateHandleRequest.Handle = CsrReply.Data.CreateProcessReply.OutputHandle;
|
||||||
|
Status = CsrClientCallServer(&CsrRequest,
|
||||||
|
&CsrReply,
|
||||||
|
sizeof(CSRSS_API_REQUEST),
|
||||||
|
sizeof(CSRSS_API_REPLY));
|
||||||
|
if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrReply.Status))
|
||||||
|
{
|
||||||
|
Ppb->hStdError = INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Ppb->hStdError = CsrReply.Data.DuplicateHandleReply.Handle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DPRINT("Duplicate error handle\n");
|
||||||
|
Status = NtDuplicateObject (NtCurrentProcess(),
|
||||||
|
Ppb->hStdError,
|
||||||
|
hProcess,
|
||||||
|
&Ppb->hStdError,
|
||||||
|
0,
|
||||||
|
TRUE,
|
||||||
|
DUPLICATE_SAME_ACCESS);
|
||||||
|
if(!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("NtDuplicateObject failed, status %x\n", Status);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: process.c,v 1.30 2003/12/02 11:38:47 gvg Exp $
|
/* $Id: process.c,v 1.31 2003/12/18 09:51:08 gvg Exp $
|
||||||
*
|
*
|
||||||
* reactos/subsys/csrss/api/process.c
|
* reactos/subsys/csrss/api/process.c
|
||||||
*
|
*
|
||||||
|
@ -252,6 +252,8 @@ CSR_API(CsrCreateProcess)
|
||||||
RtlLeaveCriticalSection(&ProcessDataLock);
|
RtlLeaveCriticalSection(&ProcessDataLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reply->Data.CreateProcessReply.Console = NewProcessData->Console;
|
||||||
|
|
||||||
Reply->Status = STATUS_SUCCESS;
|
Reply->Status = STATUS_SUCCESS;
|
||||||
return(STATUS_SUCCESS);
|
return(STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: conio.c,v 1.1 2003/12/02 11:38:46 gvg Exp $
|
/* $Id: conio.c,v 1.2 2003/12/18 09:51:08 gvg Exp $
|
||||||
*
|
*
|
||||||
* reactos/subsys/csrss/win32csr/conio.c
|
* reactos/subsys/csrss/win32csr/conio.c
|
||||||
*
|
*
|
||||||
|
@ -314,6 +314,7 @@ CSR_API(CsrAllocConsole)
|
||||||
return Reply->Status;
|
return Reply->Status;
|
||||||
}
|
}
|
||||||
ProcessData->Console = Console;
|
ProcessData->Console = Console;
|
||||||
|
Reply->Data.AllocConsoleReply.Console = Console;
|
||||||
|
|
||||||
/* add a reference count because the process is tied to the console */
|
/* add a reference count because the process is tied to the console */
|
||||||
Console->Header.ReferenceCount++;
|
Console->Header.ReferenceCount++;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: guiconsole.c,v 1.3 2003/12/07 23:02:57 gvg Exp $
|
/* $Id: guiconsole.c,v 1.4 2003/12/18 09:51:08 gvg Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS system libraries
|
* PROJECT: ReactOS system libraries
|
||||||
|
@ -482,6 +482,7 @@ GuiConsoleNotifyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
NULL,
|
NULL,
|
||||||
(HINSTANCE) GetModuleHandleW(NULL),
|
(HINSTANCE) GetModuleHandleW(NULL),
|
||||||
(PVOID) Console);
|
(PVOID) Console);
|
||||||
|
Console->hWindow = NewWindow;
|
||||||
if (NULL != NewWindow)
|
if (NULL != NewWindow)
|
||||||
{
|
{
|
||||||
SetWindowLongW(hWnd, GWL_USERDATA, GetWindowLongW(hWnd, GWL_USERDATA) + 1);
|
SetWindowLongW(hWnd, GWL_USERDATA, GetWindowLongW(hWnd, GWL_USERDATA) + 1);
|
||||||
|
@ -645,9 +646,15 @@ GuiConsoleInitConsole(PCSRSS_CONSOLE Console)
|
||||||
{
|
{
|
||||||
Console->Size.X = 80;
|
Console->Size.X = 80;
|
||||||
Console->Size.Y = 25;
|
Console->Size.Y = 25;
|
||||||
|
#ifdef TODO
|
||||||
Console->hWindow = (HWND) SendMessageW(NotifyWnd, PM_CREATE_CONSOLE, 0, (LPARAM) Console);
|
Console->hWindow = (HWND) SendMessageW(NotifyWnd, PM_CREATE_CONSOLE, 0, (LPARAM) Console);
|
||||||
|
|
||||||
return NULL != Console->hWindow;
|
return NULL != Console->hWindow;
|
||||||
|
#else
|
||||||
|
PostMessageW(NotifyWnd, PM_CREATE_CONSOLE, 0, (LPARAM) Console);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID STDCALL
|
VOID STDCALL
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: cmd.c,v 1.7 2003/08/18 11:55:43 hbirr Exp $
|
/* $Id: cmd.c,v 1.8 2003/12/18 09:51:08 gvg Exp $
|
||||||
*
|
*
|
||||||
* CMD.C - command-line interface.
|
* CMD.C - command-line interface.
|
||||||
*
|
*
|
||||||
|
@ -1228,9 +1228,6 @@ int main (int argc, char *argv[])
|
||||||
|
|
||||||
SetFileApisToOEM();
|
SetFileApisToOEM();
|
||||||
|
|
||||||
AllocConsole();
|
|
||||||
|
|
||||||
|
|
||||||
hConsole = CreateFile(_T("CONOUT$"), GENERIC_READ|GENERIC_WRITE,
|
hConsole = CreateFile(_T("CONOUT$"), GENERIC_READ|GENERIC_WRITE,
|
||||||
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
|
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
|
||||||
OPEN_EXISTING, 0, NULL);
|
OPEN_EXISTING, 0, NULL);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: winlogon.c,v 1.22 2003/12/07 00:04:20 weiden Exp $
|
/* $Id: winlogon.c,v 1.23 2003/12/18 09:51:08 gvg Exp $
|
||||||
*
|
*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -372,7 +372,7 @@ static BOOL DoLoginUser(PWCHAR Name, PWCHAR Password)
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
FALSE,
|
FALSE,
|
||||||
DETACHED_PROCESS,
|
CREATE_NEW_CONSOLE,
|
||||||
NULL,
|
NULL,
|
||||||
CurrentDirectory,
|
CurrentDirectory,
|
||||||
&StartupInfo,
|
&StartupInfo,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue