| /* |
| * common shell dialogs |
| * |
| * Copyright 2000 Juergen Schmied |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
| */ |
| |
| #include "config.h" |
| #include "wine/port.h" |
| |
| #include <string.h> |
| #include <stdarg.h> |
| #include <stdio.h> |
| #include "winerror.h" |
| #include "windef.h" |
| #include "winbase.h" |
| #include "winreg.h" |
| #include "wingdi.h" |
| #include "winuser.h" |
| #include "commdlg.h" |
| #include "wine/debug.h" |
| |
| #include "shellapi.h" |
| #include "shlobj.h" |
| #include "shell32_main.h" |
| #include "shresdef.h" |
| #include "undocshell.h" |
| |
| typedef struct |
| { |
| HWND hwndOwner ; |
| HICON hIcon ; |
| LPCWSTR lpstrDirectory ; |
| LPCWSTR lpstrTitle ; |
| LPCWSTR lpstrDescription ; |
| UINT uFlags ; |
| } RUNFILEDLGPARAMS ; |
| |
| typedef BOOL (WINAPI * LPFNOFN) (OPENFILENAMEW *) ; |
| |
| WINE_DEFAULT_DEBUG_CHANNEL(shell); |
| static INT_PTR CALLBACK RunDlgProc (HWND, UINT, WPARAM, LPARAM) ; |
| static void FillList (HWND, char *, BOOL) ; |
| |
| |
| /************************************************************************* |
| * PickIconDlg [SHELL32.62] |
| * |
| */ |
| INT WINAPI PickIconDlg(HWND hwndOwner, WCHAR *path, UINT path_len, INT *index) |
| { |
| FIXME("(%p,%s,%u,%p):stub.\n", hwndOwner, debugstr_w(path), path_len, index); |
| return 0xffffffff; |
| } |
| |
| HRESULT WINAPI SHOpenWithDialog(HWND parent, const OPENASINFO *info) |
| { |
| FIXME("stub\n"); |
| return E_NOTIMPL; |
| } |
| |
| /************************************************************************* |
| * RunFileDlgW [internal] |
| * |
| * The Unicode function that is available as ordinal 61 on Windows NT/2000/XP/... |
| * |
| * SEE ALSO |
| * RunFileDlgAW |
| */ |
| static void RunFileDlgW( |
| HWND hwndOwner, |
| HICON hIcon, |
| LPCWSTR lpstrDirectory, |
| LPCWSTR lpstrTitle, |
| LPCWSTR lpstrDescription, |
| UINT uFlags) |
| { |
| static const WCHAR resnameW[] = {'S','H','E','L','L','_','R','U','N','_','D','L','G',0}; |
| RUNFILEDLGPARAMS rfdp; |
| HRSRC hRes; |
| LPVOID template; |
| TRACE("\n"); |
| |
| rfdp.hwndOwner = hwndOwner; |
| rfdp.hIcon = hIcon; |
| rfdp.lpstrDirectory = lpstrDirectory; |
| rfdp.lpstrTitle = lpstrTitle; |
| rfdp.lpstrDescription = lpstrDescription; |
| rfdp.uFlags = uFlags; |
| |
| if (!(hRes = FindResourceW(shell32_hInstance, resnameW, (LPWSTR)RT_DIALOG)) || |
| !(template = LoadResource(shell32_hInstance, hRes))) |
| { |
| ERR("Couldn't load SHELL_RUN_DLG resource\n"); |
| ShellMessageBoxW(shell32_hInstance, hwndOwner, MAKEINTRESOURCEW(IDS_RUNDLG_ERROR), NULL, MB_OK | MB_ICONERROR); |
| return; |
| } |
| |
| DialogBoxIndirectParamW(shell32_hInstance, |
| template, hwndOwner, RunDlgProc, (LPARAM)&rfdp); |
| |
| } |
| |
| /* find the directory that contains the file being run */ |
| static LPWSTR RunDlg_GetParentDir(LPCWSTR cmdline) |
| { |
| const WCHAR *src; |
| WCHAR *dest, *result, *result_end=NULL; |
| static const WCHAR dotexeW[] = {'.','e','x','e',0}; |
| |
| result = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*(strlenW(cmdline)+5)); |
| |
| src = cmdline; |
| dest = result; |
| |
| if (*src == '"') |
| { |
| src++; |
| while (*src && *src != '"') |
| { |
| if (*src == '\\') |
| result_end = dest; |
| *dest++ = *src++; |
| } |
| } |
| else { |
| while (*src) |
| { |
| if (isspaceW(*src)) |
| { |
| *dest = 0; |
| if (INVALID_FILE_ATTRIBUTES != GetFileAttributesW(result)) |
| break; |
| strcatW(dest, dotexeW); |
| if (INVALID_FILE_ATTRIBUTES != GetFileAttributesW(result)) |
| break; |
| } |
| else if (*src == '\\') |
| result_end = dest; |
| *dest++ = *src++; |
| } |
| } |
| |
| if (result_end) |
| { |
| *result_end = 0; |
| return result; |
| } |
| else |
| { |
| HeapFree(GetProcessHeap(), 0, result); |
| return NULL; |
| } |
| } |
| |
| /* Dialog procedure for RunFileDlg */ |
| static INT_PTR CALLBACK RunDlgProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) |
| { |
| RUNFILEDLGPARAMS *prfdp = (RUNFILEDLGPARAMS *)GetWindowLongPtrW(hwnd, DWLP_USER); |
| |
| switch (message) |
| { |
| case WM_INITDIALOG : |
| prfdp = (RUNFILEDLGPARAMS *)lParam ; |
| SetWindowLongPtrW(hwnd, DWLP_USER, (LONG_PTR)prfdp); |
| |
| if (prfdp->lpstrTitle) |
| SetWindowTextW(hwnd, prfdp->lpstrTitle); |
| if (prfdp->lpstrDescription) |
| SetWindowTextW(GetDlgItem(hwnd, IDC_RUNDLG_DESCRIPTION), prfdp->lpstrDescription); |
| if (prfdp->uFlags & RFF_NOBROWSE) |
| { |
| HWND browse = GetDlgItem(hwnd, IDC_RUNDLG_BROWSE); |
| ShowWindow(browse, SW_HIDE); |
| EnableWindow(browse, FALSE); |
| } |
| if (prfdp->uFlags & RFF_NOLABEL) |
| ShowWindow(GetDlgItem(hwnd, IDC_RUNDLG_LABEL), SW_HIDE); |
| if (prfdp->uFlags & RFF_CALCDIRECTORY) |
| FIXME("RFF_CALCDIRECTORY not supported\n"); |
| |
| if (prfdp->hIcon == NULL) |
| prfdp->hIcon = LoadIconW(NULL, (LPCWSTR)IDI_WINLOGO); |
| SendMessageW(hwnd, WM_SETICON, ICON_BIG, (LPARAM)prfdp->hIcon); |
| SendMessageW(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)prfdp->hIcon); |
| SendMessageW(GetDlgItem(hwnd, IDC_RUNDLG_ICON), STM_SETICON, (WPARAM)prfdp->hIcon, 0); |
| |
| FillList (GetDlgItem (hwnd, IDC_RUNDLG_EDITPATH), NULL, (prfdp->uFlags & RFF_NODEFAULT) == 0) ; |
| SetFocus (GetDlgItem (hwnd, IDC_RUNDLG_EDITPATH)) ; |
| return TRUE ; |
| |
| case WM_COMMAND : |
| switch (LOWORD (wParam)) |
| { |
| case IDOK : |
| { |
| int ic ; |
| HWND htxt = GetDlgItem (hwnd, IDC_RUNDLG_EDITPATH); |
| if ((ic = GetWindowTextLengthW (htxt))) |
| { |
| WCHAR *psz, *parent=NULL ; |
| SHELLEXECUTEINFOW sei ; |
| |
| ZeroMemory (&sei, sizeof(sei)) ; |
| sei.cbSize = sizeof(sei) ; |
| psz = HeapAlloc( GetProcessHeap(), 0, (ic + 1)*sizeof(WCHAR) ); |
| GetWindowTextW (htxt, psz, ic + 1) ; |
| |
| /* according to http://www.codeproject.com/KB/shell/runfiledlg.aspx we should send a |
| * WM_NOTIFY before execution */ |
| |
| sei.hwnd = hwnd; |
| sei.nShow = SW_SHOWNORMAL; |
| sei.lpFile = psz; |
| |
| if (prfdp->lpstrDirectory) |
| sei.lpDirectory = prfdp->lpstrDirectory; |
| else |
| sei.lpDirectory = parent = RunDlg_GetParentDir(sei.lpFile); |
| |
| if (!ShellExecuteExW( &sei )) |
| { |
| HeapFree(GetProcessHeap(), 0, psz); |
| HeapFree(GetProcessHeap(), 0, parent); |
| SendMessageA (htxt, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ; |
| return TRUE ; |
| } |
| |
| /* FillList is still ANSI */ |
| GetWindowTextA (htxt, (LPSTR)psz, ic + 1) ; |
| FillList (htxt, (LPSTR)psz, FALSE) ; |
| |
| HeapFree(GetProcessHeap(), 0, psz); |
| HeapFree(GetProcessHeap(), 0, parent); |
| EndDialog (hwnd, 0); |
| } |
| } |
| return TRUE; |
| |
| case IDCANCEL : |
| EndDialog (hwnd, 0) ; |
| return TRUE ; |
| |
| case IDC_RUNDLG_BROWSE : |
| { |
| static const WCHAR filterW[] = {'%','s','%','c','*','.','e','x','e','%','c','%','s','%','c','*','.','*','%','c',0}; |
| HMODULE hComdlg = NULL ; |
| LPFNOFN ofnProc = NULL ; |
| static const WCHAR comdlg32W[] = {'c','o','m','d','l','g','3','2',0}; |
| WCHAR szFName[1024] = {0}; |
| WCHAR filter_exe[256], filter_all[256], filter[MAX_PATH], szCaption[MAX_PATH]; |
| OPENFILENAMEW ofn; |
| |
| LoadStringW(shell32_hInstance, IDS_RUNDLG_BROWSE_FILTER_EXE, filter_exe, 256); |
| LoadStringW(shell32_hInstance, IDS_RUNDLG_BROWSE_FILTER_ALL, filter_all, 256); |
| LoadStringW(shell32_hInstance, IDS_RUNDLG_BROWSE_CAPTION, szCaption, MAX_PATH); |
| snprintfW( filter, MAX_PATH, filterW, filter_exe, 0, 0, filter_all, 0, 0 ); |
| |
| ZeroMemory(&ofn, sizeof(ofn)); |
| ofn.lStructSize = sizeof(OPENFILENAMEW); |
| ofn.hwndOwner = hwnd; |
| ofn.lpstrFilter = filter; |
| ofn.lpstrFile = szFName; |
| ofn.nMaxFile = 1023; |
| ofn.lpstrTitle = szCaption; |
| ofn.Flags = OFN_ENABLESIZING | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST; |
| ofn.lpstrInitialDir = prfdp->lpstrDirectory; |
| |
| if (NULL == (hComdlg = LoadLibraryExW (comdlg32W, NULL, 0)) || |
| NULL == (ofnProc = (LPFNOFN)GetProcAddress (hComdlg, "GetOpenFileNameW"))) |
| { |
| ERR("Couldn't get GetOpenFileName function entry (lib=%p, proc=%p)\n", hComdlg, ofnProc); |
| ShellMessageBoxW(shell32_hInstance, hwnd, MAKEINTRESOURCEW(IDS_RUNDLG_BROWSE_ERROR), NULL, MB_OK | MB_ICONERROR); |
| return TRUE ; |
| } |
| |
| if (ofnProc(&ofn)) |
| { |
| SetFocus (GetDlgItem (hwnd, IDOK)) ; |
| SetWindowTextW (GetDlgItem (hwnd, IDC_RUNDLG_EDITPATH), szFName) ; |
| SendMessageW (GetDlgItem (hwnd, IDC_RUNDLG_EDITPATH), CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ; |
| SetFocus (GetDlgItem (hwnd, IDOK)) ; |
| } |
| |
| FreeLibrary (hComdlg) ; |
| |
| return TRUE ; |
| } |
| } |
| return TRUE ; |
| } |
| return FALSE ; |
| } |
| |
| /* This grabs the MRU list from the registry and fills the combo for the "Run" dialog above */ |
| /* fShowDefault ignored if pszLatest != NULL */ |
| static void FillList (HWND hCb, char *pszLatest, BOOL fShowDefault) |
| { |
| HKEY hkey ; |
| /* char szDbgMsg[256] = "" ; */ |
| char *pszList = NULL, *pszCmd = NULL, cMatch = 0, cMax = 0x60, szIndex[2] = "-" ; |
| DWORD icList = 0, icCmd = 0 ; |
| UINT Nix ; |
| |
| SendMessageA (hCb, CB_RESETCONTENT, 0, 0) ; |
| |
| if (ERROR_SUCCESS != RegCreateKeyExA ( |
| HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RunMRU", |
| 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL)) |
| MessageBoxA (hCb, "Unable to open registry key !", "Nix", MB_OK) ; |
| |
| RegQueryValueExA (hkey, "MRUList", NULL, NULL, NULL, &icList) ; |
| |
| if (icList > 0) |
| { |
| pszList = HeapAlloc( GetProcessHeap(), 0, icList) ; |
| if (ERROR_SUCCESS != RegQueryValueExA (hkey, "MRUList", NULL, NULL, (LPBYTE)pszList, &icList)) |
| MessageBoxA (hCb, "Unable to grab MRUList !", "Nix", MB_OK) ; |
| } |
| else |
| { |
| icList = 1 ; |
| pszList = HeapAlloc( GetProcessHeap(), 0, icList) ; |
| pszList[0] = 0 ; |
| } |
| |
| for (Nix = 0 ; Nix < icList - 1 ; Nix++) |
| { |
| if (pszList[Nix] > cMax) |
| cMax = pszList[Nix] ; |
| |
| szIndex[0] = pszList[Nix] ; |
| |
| if (ERROR_SUCCESS != RegQueryValueExA (hkey, szIndex, NULL, NULL, NULL, &icCmd)) |
| MessageBoxA (hCb, "Unable to grab size of index", "Nix", MB_OK) ; |
| if( pszCmd ) |
| pszCmd = HeapReAlloc(GetProcessHeap(), 0, pszCmd, icCmd) ; |
| else |
| pszCmd = HeapAlloc(GetProcessHeap(), 0, icCmd) ; |
| if (ERROR_SUCCESS != RegQueryValueExA (hkey, szIndex, NULL, NULL, (LPBYTE)pszCmd, &icCmd)) |
| MessageBoxA (hCb, "Unable to grab index", "Nix", MB_OK) ; |
| |
| if (NULL != pszLatest) |
| { |
| if (!lstrcmpiA(pszCmd, pszLatest)) |
| { |
| /* |
| sprintf (szDbgMsg, "Found existing (%d).\n", Nix) ; |
| MessageBoxA (hCb, szDbgMsg, "Nix", MB_OK) ; |
| */ |
| SendMessageA (hCb, CB_INSERTSTRING, 0, (LPARAM)pszCmd) ; |
| SetWindowTextA (hCb, pszCmd) ; |
| SendMessageA (hCb, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ; |
| |
| cMatch = pszList[Nix] ; |
| memmove (&pszList[1], pszList, Nix) ; |
| pszList[0] = cMatch ; |
| continue ; |
| } |
| } |
| |
| if (26 != icList - 1 || icList - 2 != Nix || cMatch || NULL == pszLatest) |
| { |
| /* |
| sprintf (szDbgMsg, "Happily appending (%d).\n", Nix) ; |
| MessageBoxA (hCb, szDbgMsg, "Nix", MB_OK) ; |
| */ |
| SendMessageA (hCb, CB_ADDSTRING, 0, (LPARAM)pszCmd) ; |
| if (!Nix && fShowDefault) |
| { |
| SetWindowTextA (hCb, pszCmd) ; |
| SendMessageA (hCb, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ; |
| } |
| |
| } |
| else |
| { |
| /* |
| sprintf (szDbgMsg, "Doing loop thing.\n") ; |
| MessageBoxA (hCb, szDbgMsg, "Nix", MB_OK) ; |
| */ |
| SendMessageA (hCb, CB_INSERTSTRING, 0, (LPARAM)pszLatest) ; |
| SetWindowTextA (hCb, pszLatest) ; |
| SendMessageA (hCb, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ; |
| |
| cMatch = pszList[Nix] ; |
| memmove (&pszList[1], pszList, Nix) ; |
| pszList[0] = cMatch ; |
| szIndex[0] = cMatch ; |
| RegSetValueExA (hkey, szIndex, 0, REG_SZ, (LPBYTE)pszLatest, strlen (pszLatest) + 1) ; |
| } |
| } |
| |
| if (!cMatch && NULL != pszLatest) |
| { |
| /* |
| sprintf (szDbgMsg, "Simply inserting (increasing list).\n") ; |
| MessageBoxA (hCb, szDbgMsg, "Nix", MB_OK) ; |
| */ |
| SendMessageA (hCb, CB_INSERTSTRING, 0, (LPARAM)pszLatest) ; |
| SetWindowTextA (hCb, pszLatest) ; |
| SendMessageA (hCb, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ; |
| |
| cMatch = ++cMax ; |
| if( pszList ) |
| pszList = HeapReAlloc(GetProcessHeap(), 0, pszList, ++icList) ; |
| else |
| pszList = HeapAlloc(GetProcessHeap(), 0, ++icList) ; |
| memmove (&pszList[1], pszList, icList - 1) ; |
| pszList[0] = cMatch ; |
| szIndex[0] = cMatch ; |
| RegSetValueExA (hkey, szIndex, 0, REG_SZ, (LPBYTE)pszLatest, strlen (pszLatest) + 1) ; |
| } |
| |
| RegSetValueExA (hkey, "MRUList", 0, REG_SZ, (LPBYTE)pszList, strlen (pszList) + 1) ; |
| |
| HeapFree( GetProcessHeap(), 0, pszCmd) ; |
| HeapFree( GetProcessHeap(), 0, pszList) ; |
| } |
| |
| /************************************************************************* |
| * RunFileDlgA [internal] |
| * |
| * The ANSI function that is available as ordinal 61 on Windows 9x/Me |
| * |
| * SEE ALSO |
| * RunFileDlgAW |
| */ |
| static void RunFileDlgA( |
| HWND hwndOwner, |
| HICON hIcon, |
| LPCSTR lpstrDirectory, |
| LPCSTR lpstrTitle, |
| LPCSTR lpstrDescription, |
| UINT uFlags) |
| { |
| WCHAR title[MAX_PATH]; /* longer string wouldn't be visible in the dialog anyway */ |
| WCHAR description[MAX_PATH]; |
| WCHAR directory[MAX_PATH]; |
| |
| MultiByteToWideChar(CP_ACP, 0, lpstrTitle, -1, title, MAX_PATH); |
| title[MAX_PATH - 1] = 0; |
| MultiByteToWideChar(CP_ACP, 0, lpstrDescription, -1, description, MAX_PATH); |
| description[MAX_PATH - 1] = 0; |
| if (!MultiByteToWideChar(CP_ACP, 0, lpstrDirectory, -1, directory, MAX_PATH)) |
| directory[0] = 0; |
| |
| RunFileDlgW(hwndOwner, hIcon, |
| lpstrDirectory ? directory : NULL, |
| lpstrTitle ? title : NULL, |
| lpstrDescription ? description : NULL, |
| uFlags); |
| } |
| |
| /************************************************************************* |
| * RunFileDlgAW [SHELL32.61] |
| * |
| * An undocumented way to open the Run File dialog. A documented way is to use |
| * CLSID_Shell, IID_IShellDispatch (as of Wine 1.0, not implemented under Wine) |
| * |
| * Exported by ordinal. ANSI on Windows 9x and Unicode on Windows NT/2000/XP/etc |
| * |
| */ |
| void WINAPI RunFileDlgAW( |
| HWND hwndOwner, |
| HICON hIcon, |
| LPCVOID lpstrDirectory, |
| LPCVOID lpstrTitle, |
| LPCVOID lpstrDescription, |
| UINT uFlags) |
| { |
| if (SHELL_OsIsUnicode()) |
| RunFileDlgW(hwndOwner, hIcon, lpstrDirectory, lpstrTitle, lpstrDescription, uFlags); |
| else |
| RunFileDlgA(hwndOwner, hIcon, lpstrDirectory, lpstrTitle, lpstrDescription, uFlags); |
| } |
| |
| |
| /************************************************************************* |
| * ConfirmDialog [internal] |
| * |
| * Put up a confirm box, return TRUE if the user confirmed |
| */ |
| static BOOL ConfirmDialog(HWND hWndOwner, UINT PromptId, UINT TitleId) |
| { |
| WCHAR Prompt[256]; |
| WCHAR Title[256]; |
| |
| LoadStringW(shell32_hInstance, PromptId, Prompt, sizeof(Prompt) / sizeof(WCHAR)); |
| LoadStringW(shell32_hInstance, TitleId, Title, sizeof(Title) / sizeof(WCHAR)); |
| return MessageBoxW(hWndOwner, Prompt, Title, MB_YESNO|MB_ICONQUESTION) == IDYES; |
| } |
| |
| |
| /************************************************************************* |
| * RestartDialogEx [SHELL32.730] |
| */ |
| |
| int WINAPI RestartDialogEx(HWND hWndOwner, LPCWSTR lpwstrReason, DWORD uFlags, DWORD uReason) |
| { |
| TRACE("(%p)\n", hWndOwner); |
| |
| /* FIXME: use lpwstrReason */ |
| if (ConfirmDialog(hWndOwner, IDS_RESTART_PROMPT, IDS_RESTART_TITLE)) |
| { |
| HANDLE hToken; |
| TOKEN_PRIVILEGES npr; |
| |
| /* enable the shutdown privilege for the current process */ |
| if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) |
| { |
| LookupPrivilegeValueA(0, "SeShutdownPrivilege", &npr.Privileges[0].Luid); |
| npr.PrivilegeCount = 1; |
| npr.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; |
| AdjustTokenPrivileges(hToken, FALSE, &npr, 0, 0, 0); |
| CloseHandle(hToken); |
| } |
| ExitWindowsEx(EWX_REBOOT, uReason); |
| } |
| |
| return 0; |
| } |
| |
| |
| /************************************************************************* |
| * RestartDialog [SHELL32.59] |
| */ |
| |
| int WINAPI RestartDialog(HWND hWndOwner, LPCWSTR lpstrReason, DWORD uFlags) |
| { |
| return RestartDialogEx(hWndOwner, lpstrReason, uFlags, 0); |
| } |
| |
| |
| /************************************************************************* |
| * ExitWindowsDialog [SHELL32.60] |
| * |
| * NOTES |
| * exported by ordinal |
| */ |
| void WINAPI ExitWindowsDialog (HWND hWndOwner) |
| { |
| TRACE("(%p)\n", hWndOwner); |
| |
| if (ConfirmDialog(hWndOwner, IDS_SHUTDOWN_PROMPT, IDS_SHUTDOWN_TITLE)) |
| { |
| HANDLE hToken; |
| TOKEN_PRIVILEGES npr; |
| |
| /* enable shutdown privilege for current process */ |
| if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) |
| { |
| LookupPrivilegeValueA(0, "SeShutdownPrivilege", &npr.Privileges[0].Luid); |
| npr.PrivilegeCount = 1; |
| npr.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; |
| AdjustTokenPrivileges(hToken, FALSE, &npr, 0, 0, 0); |
| CloseHandle(hToken); |
| } |
| ExitWindowsEx(EWX_SHUTDOWN, 0); |
| } |
| } |