@@ -579,13 +579,15 @@ static HWND SHELL_GetUsableDialogOwner(HWND hWnd)
579579}
580580
581581/* ************************************************************************
582- * SHELL32_PromptAndRunProcessAs [Internal]
582+ * PromptAndRunProcessAs [Internal]
583583 */
584- typedef struct {
585- WCHAR NameBuffer[MAX_PATH];
586- WCHAR Password[MAX_PATH];
584+ typedef struct _RUNASDLGDATA
585+ {
587586 LPWSTR Name, Domain;
588587 BOOL Safer;
588+ UINT LogonFlags;
589+ WCHAR NameBuffer[MAX_PATH];
590+ WCHAR Password[MAX_PATH];
589591} RUNASDLGDATA;
590592
591593static
@@ -622,15 +624,13 @@ RunAsDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
622624 switch (LOWORD (wParam))
623625 {
624626 case IDCANCEL:
625- EndDialog (hwnd, 1 );
627+ EndDialog (hwnd, IDCANCEL );
626628 break ;
627629
628630 case IDOK:
629631 {
630- pData->Safer = SendDlgItemMessage (hwnd, IDC_RUNAS_SAFER, BM_GETCHECK, 0 , 0 );
631- SendDlgItemMessage (hwnd, IDC_RUNAS_NAME, WM_GETTEXT, _countof (pData->NameBuffer ), (LPARAM)pData->NameBuffer );
632- SendDlgItemMessage (hwnd, IDC_RUNAS_PWD, WM_GETTEXT, _countof (pData->Password ), (LPARAM)pData->Password );
633- UINT other = SendDlgItemMessage (hwnd, IDC_RUNAS_OTHER, BM_GETCHECK, 0 , 0 ) != 0 ;
632+ SendDlgItemMessageW (hwnd, IDC_RUNAS_NAME, WM_GETTEXT, _countof (pData->NameBuffer ), (LPARAM)pData->NameBuffer );
633+ SendDlgItemMessageW (hwnd, IDC_RUNAS_PWD, WM_GETTEXT, _countof (pData->Password ), (LPARAM)pData->Password );
634634 pData->Name = pData->NameBuffer ;
635635 pData->Domain = wcsstr (pData->Name , L" \\ " );
636636 if (pData->Domain )
@@ -640,24 +640,16 @@ RunAsDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
640640 pData->Domain = pData->Name ;
641641 pData->Name = tmp;
642642 }
643- if (other)
644- {
645- HANDLE hToken;
646- if (!LogonUser (pData->Name , pData->Domain , pData->Password ,
647- LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
648- &hToken))
649- {
650- return SHELL_ErrorBox (hwnd);
651- }
652- CloseHandle (hToken);
653- other |= (GetKeyState (VK_SHIFT) & 0x8000 );
654- }
655- EndDialog (hwnd, 2 + other);
643+ pData->LogonFlags = GetKeyState (VK_SHIFT) < 0 ? LOGON_NETCREDENTIALS_ONLY : LOGON_WITH_PROFILE;
644+ pData->Safer = IsDlgButtonChecked (hwnd, IDC_RUNAS_SAFER);
645+ if (!IsDlgButtonChecked (hwnd, IDC_RUNAS_OTHER))
646+ pData->Name = NULL ;
647+ EndDialog (hwnd, IDOK);
656648 break ;
657649 }
658650
659651 case IDC_RUNAS_BROWSE:
660- return SHELL_ErrorBox (hwnd, ERROR_CALL_NOT_IMPLEMENTED ); // TODO
652+ return SHELL_ErrorBox (hwnd, ERROR_NOT_SUPPORTED ); // TODO
661653 }
662654 break ;
663655 }
@@ -666,7 +658,7 @@ RunAsDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
666658
667659static
668660HRESULT
669- SHELL32_PromptAndRunProcessAs (
661+ PromptAndRunProcessAs (
670662 _In_opt_ HWND hwnd,
671663 _In_ LPWSTR Cmd,
672664 _In_ DWORD CreationFlags,
@@ -676,31 +668,54 @@ SHELL32_PromptAndRunProcessAs(
676668 _Out_ PROCESS_INFORMATION *pPI)
677669{
678670 RUNASDLGDATA data;
679- INT_PTR dlgret = DialogBoxParamW (shell32_hInstance, MAKEINTRESOURCEW (IDD_RUN_AS),
680- SHELL_GetUsableDialogOwner (hwnd), RunAsDlgProc, (LPARAM)&data);
681- if (dlgret > 2 )
682- {
683- UINT logonFlags = (dlgret & 0x8000 ) ? LOGON_NETCREDENTIALS_ONLY : LOGON_WITH_PROFILE;
684- dlgret = CreateProcessWithLogonW (data.Name , data.Domain , data.Password , logonFlags,
685- NULL , Cmd, CreationFlags, Env, Dir, pSI, pPI);
671+ UINT error;
672+ INT_PTR dlgret;
673+ hwnd = SHELL_GetUsableDialogOwner (hwnd);
674+
675+ again:
676+ dlgret = DialogBoxParamW (shell32_hInstance, MAKEINTRESOURCEW (IDD_RUN_AS),
677+ hwnd, RunAsDlgProc, (LPARAM)&data);
678+ if (dlgret == IDOK && data.Name )
679+ {
680+ if (CreateProcessWithLogonW (data.Name , data.Domain , data.Password , data.LogonFlags ,
681+ NULL , Cmd, CreationFlags, Env, Dir, pSI, pPI))
682+ error = ERROR_SUCCESS;
683+ else
684+ error = GetLastError ();
685+ switch (error)
686+ {
687+ case ERROR_LOGON_FAILURE:
688+ case ERROR_NO_SUCH_USER:
689+ case ERROR_INVALID_ACCOUNT_NAME:
690+ case ERROR_ACCOUNT_DISABLED:
691+ case ERROR_ACCOUNT_RESTRICTION:
692+ case ERROR_INVALID_LOGON_HOURS:
693+ case ERROR_PASSWORD_EXPIRED:
694+ SHELL_ErrorBox (hwnd, error);
695+ goto again;
696+ }
686697 }
687- else if (dlgret > 1 )
698+ else if (dlgret == IDOK )
688699 {
689700 // TODO: Use the Safer API if requested to
690- dlgret = CreateProcessW (NULL , Cmd, NULL , NULL , FALSE , CreationFlags, Env, Dir, pSI, pPI);
701+ if (CreateProcessW (NULL , Cmd, NULL , NULL , FALSE , CreationFlags, Env, Dir, pSI, pPI))
702+ error = ERROR_SUCCESS;
703+ else
704+ error = GetLastError ();
691705 }
692- else if (dlgret > 0 )
706+ else if (dlgret == IDCANCEL )
693707 {
694708 SetLastError (ERROR_CANCELLED);
709+ pPI->hProcess = NULL ;
695710 return S_FALSE;
696711 }
697- SecureZeroMemory (&data, sizeof (data));
698- if (dlgret == 0 || dlgret == -1 )
712+ else
699713 {
700714 pPI->hProcess = NULL ;
701715 return E_FAIL;
702716 }
703- return S_OK;
717+ SecureZeroMemory (&data, sizeof (data));
718+ return HRESULT_FROM_WIN32 (error);
704719}
705720
706721/* ************************************************************************
@@ -715,7 +730,7 @@ static UINT_PTR SHELL_ExecuteW(const WCHAR *lpCmd, WCHAR *env, BOOL shWait,
715730 UINT_PTR retval = SE_ERR_NOASSOC;
716731 UINT gcdret = 0 , lasterror = 0 ;
717732 WCHAR curdir[MAX_PATH];
718- DWORD dwCreationFlags;
733+ DWORD dwCreationFlags = CREATE_UNICODE_ENVIRONMENT ;
719734 const WCHAR *lpDirectory = NULL ;
720735
721736 TRACE (" Execute %s from directory %s\n " , debugstr_w (lpCmd), debugstr_w (psei->lpDirectory ));
@@ -740,7 +755,6 @@ static UINT_PTR SHELL_ExecuteW(const WCHAR *lpCmd, WCHAR *env, BOOL shWait,
740755 startup.cb = sizeof (STARTUPINFOW);
741756 startup.dwFlags = STARTF_USESHOWWINDOW;
742757 startup.wShowWindow = psei->nShow ;
743- dwCreationFlags = CREATE_UNICODE_ENVIRONMENT;
744758 if (!(psei->fMask & SEE_MASK_NO_CONSOLE))
745759 dwCreationFlags |= CREATE_NEW_CONSOLE;
746760 if (psei->fMask & SEE_MASK_FLAG_SEPVDM)
@@ -774,7 +788,7 @@ static UINT_PTR SHELL_ExecuteW(const WCHAR *lpCmd, WCHAR *env, BOOL shWait,
774788 BOOL createdProcess;
775789 if (psei->lpVerb && !StrCmpIW (L" runas" , psei->lpVerb ))
776790 {
777- HRESULT hr = SHELL32_PromptAndRunProcessAs (psei->hwnd , (LPWSTR)lpCmd, dwCreationFlags,
791+ HRESULT hr = PromptAndRunProcessAs (psei->hwnd , (LPWSTR)lpCmd, dwCreationFlags,
778792 env, lpDirectory, &startup, &info);
779793 createdProcess = hr == S_OK;
780794 if (hr == S_FALSE)
0 commit comments