package main import ( "fmt" "os" "strings" ) // version is set at build time via -ldflags "-X main.version=x.y.z" var version = "dev" func main() { // DLL Hijacking 방어: DLL 탐색 경로를 System32로만 제한한다. // 게임 폴더처럼 사용자가 파일을 쓸 수 있는 디렉토리에 // 악성 DLL이 심겨 있어도 로드되지 않는다. // 반드시 다른 DLL이 로드되기 전 가장 먼저 호출해야 한다. const loadLibrarySearchSystem32 = 0x00000800 kernel32.NewProc("SetDefaultDllDirectories").Call(loadLibrarySearchSystem32) // Windows에게 "DPI는 내가 직접 처리한다"고 선언한다. // 이 선언 없이는 OS가 창을 통째로 확대해 흐릿하게 표시한다. // Per-Monitor V2: 모니터마다 DPI가 달라도 각각 대응 가능. enableDPIAwareness() // 단일 인스턴스 보장: 이미 실행 중이면 기존 창을 앞으로 가져오고 종료한다. // 내부적으로 Named Mutex("Global\A301LauncherMutex")로 중복 실행을 감지한다. if !acquireSingleInstance() { activateExistingWindow() return } // 인수 결정: 없으면 "install" (더블클릭 = 최초 설치) arg := "install" if len(os.Args) >= 2 { arg = os.Args[1] } // a301://... URI는 별도 처리 (HasPrefix라 switch로 분기 불가) if strings.HasPrefix(arg, protocolName+"://") { if err := handleURI(arg); err != nil { exitWithError(fmt.Sprintf("실행 실패:\n%v", err)) } return } switch arg { case "install": handleInstall() case "uninstall": handleUninstall() case "--version", "version": msgBox("One of the plans 런처", fmt.Sprintf("버전: %s", version), mbOK|mbInfo) default: exitWithError(fmt.Sprintf("알 수 없는 명령: %s", arg)) } }