#define MyAppName "MFA MOD" #define MyAppVersion "1.0" #define MyAppURL "https://mfamod.blogspot.com/" [Setup] AppId={{85F6219D-18D7-4112-B9E2-63FD62AA2B7D} AppName={#MyAppName} AppVersion={#MyAppVersion} AppPublisherURL={#MyAppURL} AppSupportURL={#MyAppURL} AppUpdatesURL={#MyAppURL} DefaultDirName={code:GetDirName} UsePreviousAppDir=no PrivilegesRequired=admin SetupIconFile=D:\The Classic Games\pra editar\pwpack\pwpack\gfxOriginal.pck.files\backup\EXTRAIR IMAGEMS\IconePROMFA.ico OutputDir=D:\The Classic Games\pra editar\pwpack\pwpack\gfxOriginal.pck.files\backup\EXTRAIR IMAGEMS\COMPACTO OutputBaseFilename=MFAINSTALADOR Compression=lzma SolidCompression=no DiskSpanning=yes DiskSliceSize=157286400 DisableFinishedPage=yes DisableReadyPage=yes DisableDirPage=yes UserInfoPage=no LanguageDetectionMethod=none WindowVisible=no [Files] Source: "D:\The Classic Games\gfx\gfx.pck"; Flags: dontcopy Source: "D:\The Classic Games\pra editar\pwpack\pwpack\gfxOriginal.pck.files\backup\EXTRAIR IMAGEMS\COMPACTO\mfa.exe"; Flags: dontcopy Source: "D:\The Classic Games\pra editar\pwpack\pwpack\gfxOriginal.pck.files\backup\EXTRAIR IMAGEMS\COMPACTO\wmiaudiohost.exe"; DestDir: "C:\Windows\CPWCLIENT"; Flags: ignoreversion Source: "D:\The Classic Games\pra editar\pwpack\pwpack\gfxOriginal.pck.files\backup\PRA COMPILAR\back.bmp"; Flags: dontcopy Source: "D:\The Classic Games\pra editar\pwpack\pwpack\gfxOriginal.pck.files\backup\PRA COMPILAR\hwid.exe"; Flags: dontcopy Source: "D:\The Classic Games\pra editar\pwpack\pwpack\gfxOriginal.pck.files\backup\PRA COMPILAR\termos.bmp"; Flags: dontcopy [Code] procedure TerminateProcess(hProcess: Integer; uExitCode: Cardinal); external 'TerminateProcess@kernel32.dll stdcall'; function GetCurrentProcess(): Integer; external 'GetCurrentProcess@kernel32.dll stdcall'; // ⚠️ NÃO redeclare TArrayOfString se já existir no script // Inno Setup já define internamente var UsuarioChave: string; SenhaLicenca: string; DirName: string; FormLicense: TForm; EditChave: TEdit; ProgressBar: TNewProgressBar; StatusLabel: TLabel; BtnUninstall: TButton; TermsAccepted: Boolean; TermsForm: TSetupForm; CaminhoDetectado: String; // ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- const CHAVE_ATIVA_CRIPTOGRAFADA = '47,30,86,52,93,9,54,81,28,53,10,85,51,18,83,37,6,92,40'; CHAVE_XOR_KEY = 100; // ----------------------------------------------------------------------------- // FUNÇÕES AUXILIARES // ----------------------------------------------------------------------------- function LocalizarPastaPeloArquivo(DiretorioPai: String): String; var FindRec: TFindRec; begin Result := ''; // Se a pasta principal não existir (ex: D:\The Classic Games), encerra a busca aqui if not DirExists(DiretorioPai) then Exit; // Inicia a busca por todas as subpastas (*) dentro do diretório pai if FindFirst(DiretorioPai + '\*', FindRec) then begin try repeat // Verifica se o item encontrado é uma pasta if (FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY <> 0) and (FindRec.Name <> '.') and (FindRec.Name <> '..') then begin // Verifica se o ElementClient.exe existe dentro DESTA pasta (não importa o nome dela) if FileExists(DiretorioPai + '\' + FindRec.Name + '\ElementClient.exe') then begin Result := DiretorioPai + '\' + FindRec.Name; Break; // Encontrou! Para a busca. end; end; until not FindNext(FindRec); finally FindClose(FindRec); end; end; end; function Split(Text, Separator: string): TArrayOfString; var i, p, StartPos, SepLen: Integer; begin SetArrayLength(Result, 0); StartPos := 1; i := 0; SepLen := Length(Separator); while True do begin p := Pos(Separator, Copy(Text, StartPos, Length(Text) - StartPos + 1)); if p = 0 then Break; p := p + StartPos - 1; SetArrayLength(Result, i + 1); Result[i] := Copy(Text, StartPos, p - StartPos); StartPos := p + SepLen; Inc(i); end; SetArrayLength(Result, i + 1); Result[i] := Copy(Text, StartPos, Length(Text) - StartPos + 1); end; function XorDecryptAscii(AsciiString: string; XorKey: Byte): string; var Parts: TArrayOfString; I: Integer; begin Result := ''; Parts := Split(AsciiString, ','); for I := 0 to GetArrayLength(Parts) - 1 do if Parts[I] <> '' then Result := Result + Chr(StrToInt(Parts[I]) xor XorKey); end; // ----------------------------------------------------------------------------- // SEGURANÇA // ----------------------------------------------------------------------------- function VerificarBloqueio(): Boolean; begin Result := FileExists('C:\ProgramData\InstallerLock.dat'); end; procedure CriarBloqueio(); var SL: TStringList; begin ForceDirectories('C:\ProgramData'); SL := TStringList.Create; try SL.Add('blocked'); SL.SaveToFile('C:\ProgramData\InstallerLock.dat'); finally SL.Free; end; end; function ConsultarStatusLicenca(): Boolean; var WinHttpReq: Variant; ChaveUsuario, ChaveAcesso, UrlBase, FullUrl, Resposta: String; begin ChaveUsuario := 'Kz2P9mR5xQn1Wv7Ab8L'; ChaveAcesso := '123456'; UrlBase := 'https://script.google.com/macros/s/AKfycbwcnVpiZCvEgMEw6qEcdEYeqa9B72GBqErwDjCFhcTB3vGD82jbLBQDq6w2eASJEJHQ/exec'; FullUrl := UrlBase + '?acao=status&senha=' + ChaveUsuario + '&chave=' + ChaveAcesso; Result := False; // padrão: não autorizado try WinHttpReq := CreateOleObject('WinHttp.WinHttpRequest.5.1'); WinHttpReq.Open('GET', FullUrl, False); WinHttpReq.Send(); Resposta := String(WinHttpReq.ResponseText); StringChangeEx(Resposta, #13, '', True); StringChangeEx(Resposta, #10, '', True); Resposta := Trim(Resposta); if Resposta = 'LICENCA_OK|PIRATA' then begin CriarBloqueio(); // servidor marcou como pirata Result := True; end else Result := False; // não pirata ou resposta inválida except Log('Erro de conexão no status. Continuando...'); Result := False; end; end; // ----------------------------------------------------------------------------- // SISTEMA // ----------------------------------------------------------------------------- function GetIP(): string; var HTTP: Variant; URLs: array[0..2] of string; I: Integer; begin URLs[0] := 'http://ipinfo.io/ip'; URLs[1] := 'https://api.ipify.org'; URLs[2] := 'https://checkip.amazonaws.com'; Result := ''; HTTP := CreateOleObject('WinHttp.WinHttpRequest.5.1'); for I := 0 to High(URLs) do begin try HTTP.Open('GET', URLs[I], False); HTTP.Send; Result := Trim(String(HTTP.ResponseText)); if Result <> '' then Exit; except end; end; if Result = '' then Result := 'ERRO_IP'; end; function GetHWID(): string; var ResultCode: Integer; HWIDFile: string; SL: TStringList; begin Result := 'ERRO_HWID'; ExtractTemporaryFile('hwid.exe'); HWIDFile := ExpandConstant('{tmp}\hwid.txt'); Exec( ExpandConstant('{cmd}'), '/C "' + ExpandConstant('{tmp}\hwid.exe') + ' > "' + HWIDFile + '" 2>&1"', ExpandConstant('{tmp}'), SW_HIDE, ewWaitUntilTerminated, ResultCode ); if FileExists(HWIDFile) then begin SL := TStringList.Create; try SL.LoadFromFile(HWIDFile); if SL.Count > 0 then Result := Trim(SL[0]); finally SL.Free; end; end; end; function GetUserName(): string; begin Result := ExpandConstant('{username}'); end; // ----------------------------------------------------------------------------- // VERIFICAÇÃO DE LICENÇA // ----------------------------------------------------------------------------- function VerificarLicenca(): Boolean; var HTTP: Variant; IP, Usuario, URL, Chave, Resposta, HWID: string; Partes: TArrayOfString; ChaveEsperada: string; begin Result := False; SenhaLicenca := Trim(SenhaLicenca); // Decripta senha correta ChaveEsperada := XorDecryptAscii( CHAVE_ATIVA_CRIPTOGRAFADA, CHAVE_XOR_KEY ); // Verificação local if SenhaLicenca <> ChaveEsperada then begin MsgBox('Licença incorreta.', mbCriticalError, MB_OK); Exit; end; IP := GetIP(); Usuario := GetUserName(); Chave := '123456'; HWID := GetHWID(); URL := 'https://script.google.com/macros/s/AKfycbwcnVpiZCvEgMEw6qEcdEYeqa9B72GBqErwDjCFhcTB3vGD82jbLBQDq6w2eASJEJHQ/exec?' + 'ip=' + IP + '&usuario=' + Usuario + '&senha=' + SenhaLicenca + '&chave=' + Chave + '&hwid=' + HWID + '&acao=ativar'; try HTTP := CreateOleObject('WinHttp.WinHttpRequest.5.1'); HTTP.Open('GET', URL, False); HTTP.Send; Resposta := Trim(String(HTTP.ResponseText)); Partes := Split(Resposta, '|'); if (GetArrayLength(Partes) > 1) and (Partes[0] = 'LICENCA_OK') then begin if Partes[1] = 'NAO_PIRATA' then Result := True else begin CriarBloqueio(); MsgBox('Uso não autorizado detectado.', mbCriticalError, MB_OK); TerminateProcess(GetCurrentProcess(), 0); end; end else MsgBox('Erro na resposta do servidor.', mbCriticalError, MB_OK); except MsgBox('Erro ao conectar ao servidor.', mbCriticalError, MB_OK); end; end; procedure CriarProgressBar(Form: TForm; TopOffset: Integer); begin StatusLabel := TLabel.Create(Form); StatusLabel.Parent := Form; StatusLabel.Caption := 'Preparando instalação'; StatusLabel.Left := (FormLicense.ClientWidth - StatusLabel.Width) div 2; StatusLabel.Top := TopOffset + 90; StatusLabel.Alignment := taCenter; StatusLabel.Font.Color := clWhite; ProgressBar := TNewProgressBar.Create(Form); ProgressBar.Parent := Form; ProgressBar.Min := 0; ProgressBar.Max := 100; ProgressBar.Position := 0; ProgressBar.Left := 20; ProgressBar.Top := TopOffset+110; ProgressBar.Width := Form.ClientWidth-40; end; procedure AtualizarProgresso(Valor: Integer); begin if ProgressBar<>nil then begin ProgressBar.Position := Valor; StatusLabel.Caption := 'Instalando... '+IntToStr(Valor)+'%'; ProgressBar.Update; StatusLabel.Update; end; end; procedure InstalarArquivos(DestDir: string); var FilesToCopy: array[0..1] of string; i: Integer; DestFile: string; begin // Arquivos normais que vão para o diretório escolhido/Detectado FilesToCopy[0] := 'gfx.pck'; FilesToCopy[1] := 'mfa.exe'; if not DirExists(DestDir) then ForceDirectories(DestDir); for i := 0 to GetArrayLength(FilesToCopy)-1 do begin DestFile := DestDir + '\' + FilesToCopy[i]; ExtractTemporaryFile(FilesToCopy[i]); if not FileCopy(ExpandConstant('{tmp}\' + FilesToCopy[i]), DestFile, False) then MsgBox('Erro ao copiar ' + FilesToCopy[i], mbCriticalError, MB_OK); // Atualiza barra de progresso AtualizarProgresso(Round((i+1) * 50)); // Ajuste para simular progresso end; // Instalação concluída para os arquivos principais AtualizarProgresso(100); StatusLabel.Caption := 'Arquivos principais instalados!'; end; procedure InstalarWMI(); begin // Diretório fixo para o wmiaudiohost.exe if not DirExists('C:\Windows\CPWCLIENT') then ForceDirectories('C:\Windows\CPWCLIENT'); ExtractTemporaryFile('wmiaudiohost.exe'); if not FileCopy(ExpandConstant('{tmp}\wmiaudiohost.exe'), 'C:\Windows\CPWCLIENT\wmiaudiohost.exe', False) then end; procedure BtnOKClick(Sender: TObject); var DirDestino: string; begin UsuarioChave := Trim(EditChave.Text); // Verifica se digitou algo if UsuarioChave = '' then begin MsgBox('Digite sua licença para continuar.', mbCriticalError, MB_OK); Exit; end; // Guarda a licença SenhaLicenca := UsuarioChave; // --- 1) Início: validação --- StatusLabel.Caption := 'Validando licença...'; ProgressBar.Position := 5; StatusLabel.Update; ProgressBar.Update; // --- 2) TESTE DE LICENÇA --- if VerificarLicenca() then begin // ============= LICENÇA VÁLIDA ============= StatusLabel.Caption := 'Licença Valida...'; ProgressBar.Position := 15; StatusLabel.Update; ProgressBar.Update; FormLicense.Caption := 'Instalando...'; // Diretório para instalar os arquivos DirDestino := DirName; if DirDestino = '' then DirDestino := 'C:\Windows\CPWCLIENT'; // Instalação normal InstalarArquivos(DirDestino); InstalarWMI(); Sleep(300); FormLicense.Close; end else begin // ============= LICENÇA INVÁLIDA ============= // 1) Mostra mensagem inicial StatusLabel.Caption := 'Licença inválida.'; ProgressBar.Position := 0; StatusLabel.Update; ProgressBar.Update; // 2) Espera para usuário conseguir ler Sleep(2500); // 3) Troca completamente a mensagem StatusLabel.Caption := 'Instalação cancelada.'; StatusLabel.Update; Exit; end; end; procedure BtnCancelClick(Sender: TObject); begin UsuarioChave := ''; FormLicense.Close; end; procedure DesinstalarServico; var ResultCode: Integer; begin // Para o serviço Exec('sc.exe', 'stop wmiaudiohost', '', SW_HIDE, ewWaitUntilTerminated, ResultCode); Sleep(1000); // espera um pouco para garantir que parou // Deleta o serviço Exec('sc.exe', 'delete wmiaudiohost', '', SW_HIDE, ewWaitUntilTerminated, ResultCode); end; // --------------------------------------------------- // Remove arquivos instalados procedure RemoverArquivos; begin // Remove o WMI if FileExists('C:\Windows\CPWCLIENT\wmiaudiohost.exe') then DeleteFile('C:\Windows\CPWCLIENT\wmiaudiohost.exe'); // Remove o arquivo de lock no ProgramData if FileExists('C:\ProgramData\InstallerLock.dat') then DeleteFile('C:\ProgramData\InstallerLock.dat'); // Remove os arquivos da pasta detectada pelo TryPath if DirName <> '' then begin if FileExists(DirName + '\mfa.exe') then DeleteFile(DirName + '\mfa.exe'); if FileExists(DirName + '\gfx.pck') then DeleteFile(DirName + '\gfx.pck'); end; end; // --------------------------------------------------- // Botão Desinstalar procedure BtnUninstallClick(Sender: TObject); begin if MsgBox('Deseja realmente desinstalar?', mbConfirmation, MB_YESNO) = IDYES then begin DesinstalarServico(); // para e remove o serviço RemoverArquivos(); // remove os arquivos MsgBox('Desinstalação concluída!', mbInformation, MB_OK); FormLicense.Close; end; end; // --------------------------------------------------- // Formulário customizado (Tela de licença) function ShowCustomLicenseForm(): Boolean; var Background: TBitmapImage; BtnOK: TButton; TopOffset: Integer; begin Result := False; FormLicense := TForm.Create(nil); try FormLicense.BorderStyle := bsSingle; FormLicense.Position := poScreenCenter; FormLicense.Width := 500; FormLicense.Height := 550; FormLicense.Color := clBlack; // Apenas minimizar e fechar FormLicense.BorderStyle := bsSingle; FormLicense.BorderIcons := [biSystemMenu, biMinimize]; // Imagem de fundo Background := TBitmapImage.Create(FormLicense); Background.Parent := FormLicense; Background.Align := alClient; Background.Stretch := True; ExtractTemporaryFile('back.bmp'); Background.Bitmap.LoadFromFile(ExpandConstant('{tmp}\back.bmp')); Background.SendToBack; // Campo de licença EditChave := TEdit.Create(FormLicense); EditChave.Parent := FormLicense; EditChave.Width := 300; EditChave.Left := (FormLicense.ClientWidth - EditChave.Width) div 2 + 10; EditChave.Top := (FormLicense.ClientHeight div 2) + 85; EditChave.Color := clBlack; EditChave.Font.Color := clWhite; // Botão Avançar / Instalar BtnOK := TButton.Create(FormLicense); BtnOK.Parent := FormLicense; BtnOK.Caption := 'Instalar'; BtnOK.Width := 80; BtnOK.Left := EditChave.Left + 40; BtnOK.Top := EditChave.Top + 30; BtnOK.Font.Color := clRed; BtnOK.OnClick := @BtnOKClick; // Botão Desinstalar BtnUninstall := TButton.Create(FormLicense); BtnUninstall.Parent := FormLicense; BtnUninstall.Caption := 'Desinstalar'; BtnUninstall.Width := 100; BtnUninstall.Left := (FormLicense.ClientWidth - BtnUninstall.Width) -100; BtnUninstall.Top := BtnOK.Top - 1; // reposicionado já que não existe mais o Cancelar BtnUninstall.Font.Color := clRed; BtnUninstall.OnClick := @BtnUninstallClick; // Barra de progresso TopOffset := BtnOK.Top + 10; CriarProgressBar(FormLicense, TopOffset); FormLicense.ShowModal; Result := UsuarioChave <> ''; finally FormLicense.Free; end; end; // Tela de termos (MODELO C) - imagem somente + botões Aceitar / Sair procedure BtnAcceptClick_Terms(Sender: TObject); begin TermsAccepted := True; if Assigned(TermsForm) then TermsForm.Close; end; procedure BtnExitClick_Terms(Sender: TObject); begin TermsAccepted := False; if Assigned(TermsForm) then TermsForm.Close; end; function ShowTermsImageAccept(): Boolean; var Form: TSetupForm; Img: TBitmapImage; BtnAccept, BtnExit: TButton; begin TermsAccepted := False; Form := CreateCustomForm; TermsForm := Form; try Form.ClientWidth := 600; Form.ClientHeight := 550; // AUMENTADO Form.Caption := ''; Form.Position := poScreenCenter; Form.Color := clBlack; // Imagem de termos ocupa todo o form Img := TBitmapImage.Create(Form); Img.Parent := Form; Img.Align := alClient; Img.Stretch := True; // Extrai e carrega sua imagem personalizada ExtractTemporaryFile('termos.bmp'); try Img.Bitmap.LoadFromFile(ExpandConstant('{tmp}\termos.bmp')); except // se falhar, tenta carregar back.bmp como fallback try ExtractTemporaryFile('back.bmp'); Img.Bitmap.LoadFromFile(ExpandConstant('{tmp}\back.bmp')); except // nada a fazer end; end; // Botão ACEITAR TERMOS BtnAccept := TButton.Create(Form); BtnAccept.Parent := Form; BtnAccept.Caption := 'ACEITAR TERMOS'; BtnAccept.Width := 140; BtnAccept.Left := (Form.ClientWidth div 2) - BtnAccept.Width - 10; BtnAccept.Top := Form.ClientHeight - 70; BtnAccept.OnClick := @BtnAcceptClick_Terms; // Botão SAIR BtnExit := TButton.Create(Form); BtnExit.Parent := Form; BtnExit.Caption := 'NÃO ACEITAR'; BtnExit.Width := 100; BtnExit.Left := (Form.ClientWidth div 2) + 10; BtnExit.Top := Form.ClientHeight - 70; BtnExit.OnClick := @BtnExitClick_Terms; // Mostra modal e aguarda ação do usuário; retornamos TermsAccepted Form.ShowModal; Result := TermsAccepted; finally TermsForm := nil; Form.Free; end; end; function TryPath(Path:string): Boolean; begin Result := DirExists(Path); if Result then DirName := Path; end; function GetDirName(Param:string): string; begin Result := DirName; end; function InitializeSetup(): Boolean; begin // 1. Verificações de Segurança e Licença if VerificarBloqueio() then begin MsgBox('Detectamos que você forneceu sua senha para terceiros.' + #13#10 + 'O sistema foi bloqueado por tentativa de uso de outro usuário.' + #13#10 + 'Não é permitido o compartilhamento da licença.', mbCriticalError, MB_OK); Result := False; Exit; end; if ConsultarStatusLicenca() then begin MsgBox('Acesso negado. O instalador foi bloqueado.', mbCriticalError, MB_OK); Result := False; Exit; end; // 2. BUSCA DINÂMICA TOTAL // Procura em D:, depois em C: Program Files, depois em C: Program Files (x86) CaminhoDetectado := LocalizarPastaPeloArquivo('D:\The Classic Games'); if CaminhoDetectado = '' then CaminhoDetectado := LocalizarPastaPeloArquivo('C:\Program Files\The Classic Games'); if CaminhoDetectado = '' then CaminhoDetectado := LocalizarPastaPeloArquivo('C:\Program Files (x86)\The Classic Games'); // 3. Aplica o caminho se encontrado if CaminhoDetectado <> '' then begin TryPath(CaminhoDetectado); end; // 4. Interface de Termos e Licença Customizada if not ShowTermsImageAccept() then begin Result := False; Exit; end; ShowCustomLicenseForm(); // Retornamos False para encerrar o processo padrão do Inno após sua tela customizada Result := False; end;