Загрузка данных


@echo off
setlocal EnableExtensions EnableDelayedExpansion
chcp 65001 >nul

title CypCut - установка запуска от администратора

echo.
echo ============================================================
echo       CypCut Admin Launcher - Installation
echo ============================================================
echo.

REM ============================================================
REM НАСТРОЙКИ
REM ============================================================

set "TASK_NAME=CypCut_Admin"
set "TARGET_USER=t.vol"

REM !!! ВАЖНО: Вставьте сюда SID пользователя t.vol !!!
REM Узнать SID можно командой: whoami /user (запустив от имени t.vol)
set "USER_SID=S-1-5-21-944801861-1143652485-4158720039-1686"

set "CYP_EXE=C:\Program Files (x86)\Friendess\CypCut\CypCut.exe"

set "INSTALL_DIR=C:\Program Files\CypCutLauncher"
set "LAUNCHER=%INSTALL_DIR%\CypCutLauncher.exe"

set "SOURCE=%TEMP%\CypCutLauncher.cs"

REM Рабочий стол пользователя (только имя пользователя, без домена)
set "USER_DESKTOP=C:\Users\%TARGET_USER%\Desktop"
set "SHORTCUT=%USER_DESKTOP%\CypCut.lnk"

echo Пользователь : %TARGET_USER%
echo SID          : %USER_SID%
echo CypCut       : %CYP_EXE%
echo Задача       : %TASK_NAME%
echo Лаунчер      : %LAUNCHER%
echo Ярлык        : %SHORTCUT%
echo.

if "%USER_SID%"=="" (
    echo ОШИБКА: Не указан SID пользователя!
    pause
    exit /b 1
)

REM ============================================================
REM ПРОВЕРКА ПРАВ АДМИНИСТРАТОРА
REM ============================================================

net session >nul 2>&1

if not "%errorlevel%"=="0" (
    echo.
    echo ОШИБКА:
    echo BAT необходимо запускать от имени администратора.
    echo.
    pause
    exit /b 1
)

echo [OK] Права администратора получены.
echo.

REM ============================================================
REM ПРОВЕРКА CYPcut (Используем goto, чтобы избежать проблем со скобками в (x86))
REM ============================================================

if not exist "%CYP_EXE%" goto ErrCypCut

echo [OK] CypCut найден.
echo.
goto NextCypCut

:ErrCypCut
echo.
echo ОШИБКА: CypCut не найден:
echo "%CYP_EXE%"
echo.
pause
exit /b 2

:NextCypCut

REM ============================================================
REM СОЗДАНИЕ КАТАЛОГА ЛАУНЧЕРА
REM ============================================================

echo [2/8] Создание каталога лаунчера...

if not exist "%INSTALL_DIR%" mkdir "%INSTALL_DIR%"

if not exist "%INSTALL_DIR%" (
    echo ОШИБКА создания каталога:
    echo %INSTALL_DIR%
    echo.
    pause
    exit /b 4
)

echo [OK]
echo.

REM ============================================================
REM СОЗДАНИЕ C# ИСХОДНИКА (Экранированы все закрывающие скобки)
REM ============================================================

echo [3/8] Создание C# launcher...

> "%SOURCE%" (
    echo using System;
    echo using System.Diagnostics;
    echo using System.Runtime.InteropServices;
    echo.
    echo class CypCutLauncher
    echo {
    echo     const int CREATE_UNICODE_ENVIRONMENT = 0x00000400;
    echo     const int CREATE_NEW_CONSOLE = 0x00000010;
    echo     const int STARTF_USESHOWWINDOW = 0x00000001;
    echo     const short SW_SHOW = 5;
    echo.
    echo     [StructLayout(LayoutKind.Sequential^)]
    echo     struct STARTUPINFO
    echo     {
    echo         public int cb;
    echo         public string lpReserved;
    echo         public string lpDesktop;
    echo         public string lpTitle;
    echo         public int dwX;
    echo         public int dwY;
    echo         public int dwXSize;
    echo         public int dwYSize;
    echo         public int dwXCountChars;
    echo         public int dwYCountChars;
    echo         public int dwFillAttribute;
    echo         public int dwFlags;
    echo         public short wShowWindow;
    echo         public short cbReserved2;
    echo         public IntPtr lpReserved2;
    echo         public IntPtr hStdInput;
    echo         public IntPtr hStdOutput;
    echo         public IntPtr hStdError;
    echo     }
    echo.
    echo     [StructLayout(LayoutKind.Sequential^)]
    echo     struct PROCESS_INFORMATION
    echo     {
    echo         public IntPtr hProcess;
    echo         public IntPtr hThread;
    echo         public int dwProcessId;
    echo         public int dwThreadId;
    echo     }
    echo.
    echo     [DllImport("kernel32.dll"^)]
    echo     static extern int WTSGetActiveConsoleSessionId(^);
    echo.
    echo     [DllImport("wtsapi32.dll", SetLastError = true^)]
    echo     static extern bool WTSQueryUserToken(
    echo         int SessionId,
    echo         out IntPtr phToken^);
    echo.
    echo     [DllImport("advapi32.dll", SetLastError = true^)]
    echo     static extern bool DuplicateTokenEx(
    echo         IntPtr hExistingToken,
    echo         uint dwDesiredAccess,
    echo         IntPtr lpTokenAttributes,
    echo         int ImpersonationLevel,
    echo         int TokenType,
    echo         out IntPtr phNewToken^);
    echo.
    echo     [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode^)]
    echo     static extern bool CreateProcessAsUser(
    echo         IntPtr hToken,
    echo         string lpApplicationName,
    echo         string lpCommandLine,
    echo         IntPtr lpProcessAttributes,
    echo         IntPtr lpThreadAttributes,
    echo         bool bInheritHandles,
    echo         uint dwCreationFlags,
    echo         IntPtr lpEnvironment,
    echo         string lpCurrentDirectory,
    echo         ref STARTUPINFO lpStartupInfo,
    echo         out PROCESS_INFORMATION lpProcessInformation^);
    echo.
    echo     [DllImport("userenv.dll", SetLastError = true^)]
    echo     static extern bool CreateEnvironmentBlock(
    echo         out IntPtr lpEnvironment,
    echo         IntPtr hToken,
    echo         bool bInherit^);
    echo.
    echo     [DllImport("userenv.dll", SetLastError = true^)]
    echo     static extern bool DestroyEnvironmentBlock(
    echo         IntPtr lpEnvironment^);
    echo.
    echo     [DllImport("kernel32.dll", SetLastError = true^)]
    echo     static extern bool CloseHandle(IntPtr hObject^);
    echo.
    echo     static void Main(^)
    echo     {
    echo         string exe = @"C:\Program Files (x86)\Friendess\CypCut\CypCut.exe";
    echo.
    echo         if (!System.IO.File.Exists(exe^)^)
    echo         {
    echo             Environment.Exit(10^);
    echo             return;
    echo         }
    echo.
    echo         int sessionId = WTSGetActiveConsoleSessionId(^);
    echo.
    echo         if (sessionId == -1^)
    echo         {
    echo             Environment.Exit(11^);
    echo             return;
    echo         }
    echo.
    echo         IntPtr userToken;
    echo.
    echo         if (!WTSQueryUserToken(sessionId, out userToken^)^)
    echo         {
    echo             Environment.Exit(Marshal.GetLastWin32Error(^)^);
    echo             return;
    echo         }
    echo.
    echo         IntPtr primaryToken;
    echo.
    echo         if (!DuplicateTokenEx(
    echo             userToken,
    echo             0xF01FF,
    echo             IntPtr.Zero,
    echo             2,
    echo             1,
    echo             out primaryToken^)^)
    echo         {
    echo             int err = Marshal.GetLastWin32Error(^);
    echo             CloseHandle(userToken^);
    echo             Environment.Exit(err^);
    echo             return;
    echo         }
    echo.
    echo         IntPtr environment = IntPtr.Zero;
    echo         CreateEnvironmentBlock(out environment, primaryToken, false^);
    echo.
    echo         STARTUPINFO si = new STARTUPINFO(^);
    echo         si.cb = Marshal.SizeOf(typeof(STARTUPINFO^)^);
    echo         si.lpDesktop = @"winsta0\default";
    echo         si.dwFlags = STARTF_USESHOWWINDOW;
    echo         si.wShowWindow = SW_SHOW;
    echo.
    echo         PROCESS_INFORMATION pi;
    echo.
    echo         string commandLine = "\"" + exe + "\"";
    echo.
    echo         bool result = CreateProcessAsUser(
    echo             primaryToken,
    echo             exe,
    echo             commandLine,
    echo             IntPtr.Zero,
    echo             IntPtr.Zero,
    echo             false,
    echo             CREATE_UNICODE_ENVIRONMENT ^| CREATE_NEW_CONSOLE,
    echo             environment,
    echo             System.IO.Path.GetDirectoryName(exe^),
    echo             ref si,
    echo             out pi^);
    echo.
    echo         int lastError = Marshal.GetLastWin32Error(^);
    echo.
    echo         if (environment != IntPtr.Zero^)
    echo             DestroyEnvironmentBlock(environment^);
    echo.
    echo         CloseHandle(userToken^);
    echo         CloseHandle(primaryToken^);
    echo.
    echo         if (!result^)
    echo         {
    echo             Environment.Exit(lastError^);
    echo             return;
    echo         }
    echo.
    echo         CloseHandle(pi.hThread^);
    echo         CloseHandle(pi.hProcess^);
    echo.
    echo         Environment.Exit(0^);
    echo     }
    echo }
)

if not exist "%SOURCE%" (
    echo ОШИБКА создания C# файла.
    echo.
    pause
    exit /b 5
)

echo [OK] C# исходник создан.
echo.

REM ============================================================
REM ПОИСК CSC.EXE
REM ============================================================

echo Поиск csc.exe...

set "CSC="

if exist "%WINDIR%\Microsoft.NET\Framework64\v4.0.30319\csc.exe" (
    set "CSC=%WINDIR%\Microsoft.NET\Framework64\v4.0.30319\csc.exe"
)

if not defined CSC if exist "%WINDIR%\Microsoft.NET\Framework\v4.0.30319\csc.exe" (
    set "CSC=%WINDIR%\Microsoft.NET\Framework\v4.0.30319\csc.exe"
)

if not defined CSC (
    echo.
    echo ОШИБКА: csc.exe не найден.
    echo.
    pause
    exit /b 6
)

echo [OK] CSC:
echo %CSC%
echo.

REM ============================================================
REM КОМПИЛЯЦИЯ C#
REM ============================================================

echo Компиляция CypCutLauncher.exe...

"%CSC%" /nologo /target:exe /platform:anycpu /optimize+ /out:"%LAUNCHER%" "%SOURCE%"

if errorlevel 1 (
    echo.
    echo ОШИБКА компиляции C#.
    echo.
    pause
    exit /b 7
)

if not exist "%LAUNCHER%" (
    echo.
    echo ОШИБКА: CypCutLauncher.exe не создан.
    echo.
    pause
    exit /b 8
)

echo [OK] CypCutLauncher.exe создан.
echo.

REM ============================================================
REM УДАЛЕНИЕ СТАРОЙ ЗАДАЧИ
REM ============================================================

echo [4/8] Удаление старой задачи...

schtasks /delete /tn "%TASK_NAME%" /f >nul 2>&1

echo [OK]
echo.

REM ============================================================
REM СОЗДАНИЕ ЗАДАЧИ
REM ============================================================

echo [5/8] Создание задачи %TASK_NAME%...

powershell.exe -NoProfile -ExecutionPolicy Bypass -Command ^
"$action = New-ScheduledTaskAction -Execute '%LAUNCHER%'; ^
$principal = New-ScheduledTaskPrincipal -UserId 'SYSTEM' -LogonType ServiceAccount -RunLevel Highest; ^
$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries; ^
Register-ScheduledTask -TaskName '%TASK_NAME%' -Action $action -Principal $principal -Settings $settings -Force"

if errorlevel 1 (
    echo.
    echo ОШИБКА создания задачи.
    echo.
    pause
    exit /b 9
)

echo [OK] Задача создана.
echo.

REM ============================================================
REM РАЗРЕШЕНИЕ t.vol НА ЗАПУСК ЗАДАЧИ
REM ============================================================

echo [6/8] Настройка разрешений задачи для %TARGET_USER%...

powershell.exe -NoProfile -ExecutionPolicy Bypass -Command ^
"$service = New-Object -ComObject 'Schedule.Service'; ^
$service.Connect(); ^
$task = $service.GetFolder('\').GetTask('%TASK_NAME%'); ^
$sd = $task.GetSecurityDescriptor(4); ^
$sid = '%USER_SID%'; ^
$ace = '(A;;FR;;;' + $sid + ')'; ^
if ($sd -notmatch [regex]::Escape($ace)) { ^
    if ($sd.StartsWith('D:')) { ^
        $sd = 'D:' + $ace + $sd.Substring(2) ^
    } else { ^
        $sd = $sd + $ace ^
    }; ^
    $task.SetSecurityDescriptor($sd, 4) ^
}"

if errorlevel 1 (
    echo.
    echo ВНИМАНИЕ: не удалось изменить разрешения задачи.
    echo.
) else (
    echo [OK] Разрешение на запуск задачи добавлено.
)

echo.

REM ============================================================
REM ПРАВА НА LAUNCHER
REM ============================================================

icacls "%LAUNCHER%" /grant "*%USER_SID%:(RX)" >nul

echo [OK] Права на CypCutLauncher.exe настроены.
echo.

REM ============================================================
REM СОЗДАНИЕ ЯРЛЫКА НА РАБОЧЕМ СТОЛЕ t.vol
REM ============================================================

echo [7/8] Создание ярлыка на рабочем столе...

if not exist "%USER_DESKTOP%" (
    mkdir "%USER_DESKTOP%" >nul 2>&1
)

powershell.exe -NoProfile -ExecutionPolicy Bypass -Command ^
"$ws = New-Object -ComObject WScript.Shell; ^
$shortcut = $ws.CreateShortcut('%SHORTCUT%'); ^
$shortcut.TargetPath = '%SystemRoot%\System32\schtasks.exe'; ^
$shortcut.Arguments = '/run /tn ""%TASK_NAME%""'; ^
$shortcut.WorkingDirectory = '%SystemRoot%\System32'; ^
$shortcut.Description = 'Запуск CypCut от имени администратора'; ^
$shortcut.IconLocation = '%CYP_EXE%,0'; ^
$shortcut.WindowStyle = 7; ^
$shortcut.Save()"

if not exist "%SHORTCUT%" (
    echo.
    echo ВНИМАНИЕ: ярлык не создан.
    echo Проверьте:
    echo %USER_DESKTOP%
    echo.
) else (
    echo [OK] Ярлык создан:
    echo %SHORTCUT%
)

echo.

REM ============================================================
REM ОЧИСТКА
REM ============================================================

echo [8/8] Очистка временных файлов...

del /q "%SOURCE%" >nul 2>&1

echo [OK]
echo.

REM ============================================================
REM ПРОВЕРКА
REM ============================================================

echo ============================================================
echo                  УСТАНОВКА ЗАВЕРШЕНА
echo ============================================================
echo.
echo Задача:
echo   %TASK_NAME%
echo.
echo Launcher:
echo   %LAUNCHER%
echo.
echo Ярлык:
echo   %SHORTCUT%
echo.
echo Пользователь:
echo   %TARGET_USER%
echo.
echo SID:
echo   %USER_SID%
echo.
echo ============================================================
echo.

echo Проверяем задачу...
echo.

schtasks /query /tn "%TASK_NAME%" /v /fo list

echo.
echo ============================================================
echo.
echo Теперь пользователь %TARGET_USER% может дважды
echo щёлкнуть ярлык CypCut на рабочем столе.
echo.
echo Ручная проверка:
echo.
echo   schtasks /run /tn "%TASK_NAME%"
echo.
echo ============================================================
echo.

pause
exit /b 0