quarta-feira, 13 de abril de 2011

Para descontrair hoje








Uma boa tarde a todos!

Sobre livros

Eu gosto de ler. Não sou um rato de biblioteca, não tenho leitura dinâmica e não leio tão rápido ou com tanta frequência (sem trema desta vez), mas gosto de ler.
Gosto de comparar uma boa leitura com uma boa refeição. Já percebeu que às vezes um prato simples, em um restaurante pequeno de um bairro não muito movimentado pode te surpreender? Pode ser exatamente igual ao que sua mãe fazia, por exemplo.
O mesmo acontece com livros. Às vezes não damos muita atenção para um livro, e ele nos surpreende. Não apenas pela história envolvente, mas pelas "notas". Sim, notas. Para quem degusta vinhos, café ou perfumes está acostumado a ouvir essa palavra, "notas", fora de um contexto musical. Nos vinhos, pratos e perfumes notas são características, que não são plenamente fixas ou mensuráveis, mas são nebulosas. Não têm extremos, mas têm infinitas gradações.
Quantas gradações de sabor podem existir entre o amargo do café e o doce do chocolate? Entre um perfume e outro?
Essas "notas" podem ser encontradas em livros. E não apenas em romances ou ficções, mas em livros técnicos, enciclopédias, trabalhos científicos, quadrinhos, livros religiosos etc... Elas atingem sua mente, ressoam no seu intelecto, reverberam no seu íntimo, retinem em sua alma, misturam-se a todas as suas crenças, filosofias, conhecimentos tácitos e personalidade. Por fim são incorporadas e tornam parte do seu próprio acervo, de você. Essas notas também são chamadas de memes, mas memes hoje ganharam um significado marqueteiro interneteiro muito aquém do seu real significado.
Se comparados à refeições uma revista é como um lanche em um fast-food americano. Um livro técnico é como um prato-feito de buteco: quantidade grande, comida demasiadamente comum (ou até ordinária), muita gordura e carboidrato, em frente ao seu trabalho, te preparando para o trabalho, pronto para o trabalho. Sim, da mesma forma que você só come o "pf" no buteco em frente à empresa quando está trabalhando, livros técnicos só servem para trabalho. Eles SÃO trabalho. Mas, da mesma forma que o pf, nem tudo será comido, e nem tudo será digerido. Ou você vai me dizer que devora com prazer os livros técnicos de capa a capa, mesmo as partes que você já está "saciado", mesmo sem fome desse conhecimento, e ainda assim fica mais "saudável"? Dirá que a cada livro técnico devorado seu salário aumenta 1%, 0,1%?
Livros técnicos são importantes, como o arroz, feijão, bife e salada. Mas não deveriam ser os únicos livros da  sua vida.
Recentemente eu li um livro desses, baratinho, de bolso, comprado em banca de jornal, que não valorizei muito quando vi, mas que ele se mostrou uma macarronada de domingo, com direito a frango à passarinho.
O diário do chaves vai além do que é mostrado nos episódios do seriado e, sem perder o tom de comédia, mostra um lado mais dramático, triste e até lúgubre da história.
Não vou falar mais nada, porque irá estragar sua refeição. Apenas recomendo: experimente.







Atualização:
Meio esfomeado estou hoje não? É que minha inspiração para o texto acima foi esse livro-mangá aqui:
Sentimentos se misturam num belo prato, marcados por um ritmo, um passo, intenso como a correria da vida, onde apenas nos momentos de saciar o vazio em seu estômago é que o personagem se apercebe do seu vazio existencial.
Eu gostei.

quinta-feira, 7 de abril de 2011

Uma grande verdade sobre tecnologia



Vai dizer que não é verdade.

quarta-feira, 6 de abril de 2011

Clube Delphi 128

Saiu a Clube Delphi 128, e dessa vez o meu artigo é capa! Agradeço ao Guinther Pauli, editor da revista, pela paciência que tem com meus atrasos :p

Meu artigo sobre interoperabilidade explica como integrar sistemas Delphi Win32, .Net e talvez outros através de DLLs, COM, WebServices e troca de mensagens pela API do windows.

Mostro nesse artigo como consumir uma DLL feita em Delphi através do .Net, como consumir pelo Delphi uma DLL .Net através da integração COM, como consumir pelo Delphi um webservice feito em .Net e como fazer as aplicações se comunicarem via API do windows.

Lógico, sobre interoperabilidade fiquei devendo, por questões de tempo e espaço, algumas coisinhas que pretendo mencionar em artigos futuros, na revista e/ou neste blog:



  1. .Net consumindo webservice em Delphi
  2.  Introdução do Lazarus na brincadeira
  3.  Integração por sockets
  4.  Integração por xml, json e txt

Por enquanto não vejo a hora de ler os artigos sobre programação Android com freepascal e o artigo sobreXML Data Binding.

Espero que todos tenham uma boa leitura ;)

Verdades sobre programação

Esse blog, do @luisdalmolin, contém um excelente texto sobre verdades não tão conhecidas sobre programação. Não tão conhecidas talvez pelos nossos chefes / stakeholders, mas muito bem conhecidas por nós. O post foi traduzido desse aqui  em inglês.

Basicamente, o texto fala sobre o que já sabemos:
1) Dez programadores não farão o programa em um décimo do tempo assim como nove mulheres não fazem um bebê em um mês. (apenas uma grande suruba lésbica).
2) Bons programadores passam muito mais tempo lendo, estudando, pensando, refatorando do que escrevendo, codificando e debugando. É fato! Scrum e XP pregam isso. O resto é XGH (eXtreme Go Horse).
3) Programadores (e hoje analistas de sistemas também) são tratados como peões, na rabeira do organograma da empresa, muitas vezes mesmo se destacando em sua área, possuindo graduação, pós graduação e certificações, o que significa que um programador é tratado como um operário mesmo tendo estudado tanto quanto (em alguns casos muito mais) um médico ou advogado, e continuar estudando ao longo de TODA sua carreira.
4) Planejamento é fundamental antes, durante e depois.
5) Mesmo os requisitos sendo flexíveis, isso não significa "festa do caqui" com os requisitos. E os prazos e escopo deveriam ser flexíveis proporcionalmente à flexibilidade dos requisitos.
6) Mudanças de requisitos geram entropia, ok, mas mudanças sem planejamento, sem levantamento de requisitos, direto no código, por meio de tentativa e erro até funcionar geram mais entropia ainda, tendendo ao caos, e inevitavelmente vão falhar. FALHARÃO MISERAVELMENTE.

Alguns quadrinhos humorísticos tirados do site Vida de Programador ilustram isso:



Essa outra ilustra bem a situação.


Não podemos esquecer do vídeo hug a developer! Ele ilustra de maneira bem humorada os problemas, desafios e DORES pelas quais um programador passa nas mãos e chefes porcos, cães sarnentos ignorantes ...


terça-feira, 5 de abril de 2011

Enquanto isso, em algum lugar da internet

Para descontrair...






E para quem trabalha com suporte:

IPS VIZINHOS
  • QA:
    Oi, usuário tá conectando com o IP 189.21.22.23 e não tá funcionando
  • DBA:
    Mas o IP aqui no banco de dados é o 189.22.23.25... Tem algo errado aí
  • QA:
    Ah, não são iguais, mas são bem próximos né?


fonte: http://fuckyeahdementia.com/ e http://fuckyeahitbullshit.tumblr.com/

segunda-feira, 4 de abril de 2011

A API GetuserNameEx

Primeiro de tudo, a função GetUserNameEx se encontra na dll Secur32.dll e, como outras funções da API do windows, possui duas versões, uma ANSI (GetUserNameExA) e uma WIDE (GetUserNameExW).

Abaixo segue o cabeçalho para importação dessas duas funções.

function GetUserNameExA(NameFormat: TEXTENDED_NAME_FORMAT; lpBuffer: PAnsiChar; var nSize: DWORD): BOOL; stdcall external 'Secur32.dll' name 'GetUserNameExA';
function GetUserNameExW(NameFormat: TEXTENDED_NAME_FORMAT; lpBuffer: PWideChar; var nSize: DWORD): BOOL; stdcall external 'Secur32.dll' name 'GetUserNameExW';


Atenção especial para o parâmetro NameFormat do tipo TEXTENDED_NAME_FORMAT. Ele é na verdade um Enum com alguns valores fixos. (no C também é um enum, e usa-se um ponteiro para ele)

  TEXTENDED_NAME_FORMAT  =
  (
    NameUnknown            = 0,
    NameFullyQualifiedDN   = 1,
    NameSamCompatible      = 2,
    NameDisplay            = 3,
    NameUniqueId           = 6,
    NameCanonical          = 7,
    NameUserPrincipal      = 8,
    NameCanonicalEx        = 9,
    NameServicePrincipal   = 10,
    NameDnsDomain          = 12
  );

Criei essas duas funções que me retornam uma string (UnicodeString no Delphi 2010) ou AnsiString para testar e facilitar o uso da GetUserNameEx (A ou W).

function TForm1.VtrGetUserNameExW(NameFormat: TEXTENDED_NAME_FORMAT): string;
var
  I: DWord;
begin
  I := 1000;
  SetLength(Result, I);
  GetUserNameExW(NameFormat, PChar(Result), I);
  Result := string(PChar(Result));
end;

function TForm1.VtrGetUserNameExA(NameFormat: TEXTENDED_NAME_FORMAT): AnsiString;
var
  I: DWord;
begin
  I := 1000;
  SetLength(Result, I);
  GetUserNameExA(NameFormat, PAnsiChar(Result), I);
  Result := AnsiString(PAnsiChar(Result));
end;



Estou alocando um espaço de 1000 caracteres para o resultado. É arbitrário. Quem souber uma maneira melhor de fazer isso, talvez usando outra api para saber o tamanho do nome do usuário de antemão, por favor me avise.

para testar chamo todas as funções, GetUserNameEx (A e W) passando todos os parâmetros possíveis de NameUnknown (0) a NameDnsDomain (12) e vejo o resultado.

procedure TForm1.Button2Click(Sender: TObject);
var
  enf: TEXTENDED_NAME_FORMAT;
begin
    Memo1.Lines.Add('Versão Wide -----------------------------------');
    enf := NameUnknown;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExW(enf));

    enf := NameFullyQualifiedDN;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExW(enf));

    enf := NameSamCompatible;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExW(enf));

    enf := NameDisplay;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExW(enf));

    enf := NameUniqueId;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExW(enf));

    enf := NameCanonical;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExW(enf));

    enf := NameUserPrincipal;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExW(enf));

    enf := NameCanonicalEx;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExW(enf));

    enf := NameServicePrincipal;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExW(enf));

    enf := NameDnsDomain;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExW(enf));


    Memo1.Lines.Add('Versão Ansi -----------------------------------');
    enf := NameUnknown;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExA(enf));

    enf := NameFullyQualifiedDN;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExA(enf));

    enf := NameSamCompatible;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExA(enf));

    enf := NameDisplay;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExA(enf));

    enf := NameUniqueId;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExA(enf));

    enf := NameCanonical;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExA(enf));

    enf := NameUserPrincipal;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExA(enf));

    enf := NameCanonicalEx;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExA(enf));

    enf := NameServicePrincipal;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExA(enf));

    enf := NameDnsDomain;
    Memo1.Lines.Add(inttostr(integer(enf)) +' ' + VtrGetUserNameExA(enf));

end;


Api hooking para mudar o usuário logado

Já está nas bancas a revista Clube Delphi 127 com meu primeiro artigo sobre a madShi Collection. Neste artigo eu explico o básico sobre API Hooking.

Neste post falarei sobre um exemplo que não se encontra no artigo, que é o hooking da API GetUserName.
Os motivos que levam a hookar essa API podem ser variados, e todos eles nada éticos a meu ver. Você pode desde tentar enganar um produto registrado para um usuário acessando-o como outro usuário ou simplesmente para tapear um usuário administrador, que quando olhar quem está logado verá um nome diferente (supondo que isso funcione, não testei).

A idéia é que dá para mudar a resposta que outros programas recebem quando perguntam quem é o usuário logado. Para isso é necessário conhecer quais são as api's que fazem isso e como interceptá-las.

O código dessa postagem mostra como usar a madCodeHook para interceptar a api GetUserName da api do windows.

Primeiro de tudo criei um programa que mostra o nome do usuário corrente:


function NomeUsuario: string;
var
  I: DWord;
begin
  I := 255;
  SetLength(Result, I);
  Windows.GetUserName(PChar(Result), I);
  Result := string(PChar(Result));
end;



procedure TForm2.btTestarClick(Sender: TObject);

begin
  Edit1.Text := NomeUsuario;
end;



Esse programa simplesmente mostra o usuário logado. Depois de injetada a DLL que faz o hook a chamada a GetUserName terá seu resultado mudado.
É preciso salientar que existe outra api chamada GetUserNameEx que não está mapeada na unit windows.pas e que aceita mais parâmetros, e devolve mais resultados.

Interceptar essas duas API's é certeza de que mudará os resultados às suas relativas chamadas. Não é garantia nenhuma de que será possível abrir um arquivo para o qual seu usuário atual não tem autorização, mas não custa nada tentar.

Como pôde ser visto nos artigos que escrevi para a Revista Clube Delphi, eis o código da dll a ser injetada.

Essa dll intercepta apenas a função GetUserName, deixo a cargo do leitor a GetUserNamneEx, que é mais complexa. Num post futuro trataremos da GetUserNameEx. Deixo apenas o esqueleto para quem quiser se aventurar.

Lembre-se de que se estiver usando a versão trial/demo da madCollectionHook deverá manter mchEvaluation rodando para que o hooking funcione.

library hook;

uses
  SysUtils,
  windows,
  Classes,
  madcodehook;

{$R *.res}


const
  USUORIGINAL =  'vitorrubio';    //       vitorrubio --> meu user
  USUTROCA = 'Administrador';       //       Administrador--> quem quero ser




var
  GetUserNameWNext:  function (lpBuffer: PWideChar; var nSize: DWORD): BOOL; stdcall;
  GetUserNameANext:  function (lpBuffer: PAnsiChar; var nSize: DWORD): BOOL; stdcall;


function GetUserNameWCallback (lpBuffer: PWideChar; var nSize: DWORD): BOOL; stdcall;
begin

  Result := GetUserNameWNext(lpBuffer, nSize);
  if (trim(string(lpBuffer)) = USUORIGINAL) then
  begin
    StrCopy(lpBuffer, USUTROCA);
    nSize := Length(USUTROCA);
  end;

end;

function GetUserNameACallback (lpBuffer: PAnsiChar; var nSize: DWORD): BOOL; stdcall;
begin

  Result := GetUserNameANext(lpBuffer, nSize);
  if (trim(AnsiString(lpBuffer)) = AnsiString(USUORIGINAL)) then
  begin
    StrCopy(lpBuffer, USUTROCA);
    nSize := Length(USUTROCA);
  end;

end;

begin
  HookAPI('advapi32.dll', 'GetUserNameW',  @GetUserNameWCallback, @GetUserNameWNext);
  HookAPI('advapi32.dll', 'GetUserNameA',  @GetUserNameACallback, @GetUserNameANext);
end.


Agora o código para injetar, desinjetar e testar a dll:

procedure TForm1.btInjetarClick(Sender: TObject);
begin
  InjectLibrary(ALL_SESSIONS or SYSTEM_PROCESSES, 'hook.dll');
end;

procedure TForm1.btTestarClick(Sender: TObject);
begin
  Edit1.Text := NomeUsuario;
end;

procedure TForm1.btDesinjetarClick(Sender: TObject);
begin
  UninjectLibrary(ALL_SESSIONS or SYSTEM_PROCESSES, 'hook.dll');
end;

Crie uma form com 3 botões e um edit e teste. Lembre-se de todas as medidas de segurança necessárias para se trabalhar com API hooking e lembre-se que toda a api do windows se invoca com stdcall.

Coloque a dll e o testador em um mesmo project group para facilitar.

É importante salientar que qualquer processo que use a GetUserNameEx para identificar o usuário não sofrerá nenhum efeito desse hooking. Além disso o windows tem outras formas, de baixo nível, para descobrir o usuário logado.

Have fun :)

sexta-feira, 1 de abril de 2011

Primeiro de Abril dos programadores

Quem é do ramo de TI sabe o que são as normas RFC. São conjuntos de convenções onde são estabelecidos padrões para que computadores possam se comunicar e trocar dados entre si, e para que esses dados sejam reconhecidos por todos. Se não fossem essas normas o mundo da TI seria um caos (e já não é).

É insteressante o fato de que a norma RFC 2550 foi criada em 1° de abril de 1999, e tratava do bug y2k, o bug do milênio. Desde que a convenção de dadas expressa em 2 dígitos para o ano foi criada sabia-se que em 2000 isso ia dar merda parar de funcionar, mas mesmo assim a solução foi deixada para 1999, a véspera.

Lendo a norma, é possível encontrar o seguinte texto, bem - humorado apesar da seriedade e sobriedade das normas RFC:


" Nearly everyone now regrets the
   short-sightedness of the programmers of yore who wrote programs
   designed to fail in the year 2000.  Unfortunately, the current fixes
   for Y2K lead inevitably to a crisis in the year 10,000 when the
   programs are again designed to fail."


Numa tradução livre:

"Quase todo mundo lamenta a falta de visão dos programadores de antigamente, que criaram os programas já designados para falhar em 2000. Infelizmente, as correções correntes para o Y2K conduzirão inevitavelmente a uma crise no ano 10.000, quando os programas falharão novamente"

Sei lá, eu nunca esperaria encontrar esse tipo de ironia sutil numa norma RFC mas é a mais pura realidade: prepare-se porque todos os programas falharão no ano 10.000, o que fizemos foi uma gambiarra que tem 8000 anos de duração.

Há também na norma um padrão de nomenclatura para o bug do ano 10.000, chamado de YXK, em algarismos romanos (X) ou YAK, em hexadecimal (A = 10).

Seja pró-ativo, não espere o pior acontecer, antecipe-se, corrija agora mesmo o bug do ano 10.000 no seu software :)

Isso poderá gerar royalties e patentes para os seus tatatatatatatatatatatatatatatata (são 14 ou mais tatas?) ranetos.

Postagens populares

Marcadores

delphi (60) C# (31) poo (21) Lazarus (19) Site aos Pedaços (15) sql (13) Reflexões (10) .Net (9) Humor (9) javascript (9) ASp.Net (8) api (8) Básico (6) Programação (6) ms sql server (5) Web (4) banco de dados (4) HTML (3) PHP (3) Python (3) design patterns (3) jQuery (3) livros (3) metaprogramação (3) Ajax (2) Debug (2) Dicas Básicas Windows (2) Pascal (2) games (2) linguagem (2) música (2) singleton (2) tecnologia (2) Anime (1) Api do Windows (1) Assembly (1) Eventos (1) Experts (1) GNU (1) Inglês (1) JSON (1) SO (1) datas (1) developers (1) dicas (1) easter egg (1) firebird (1) interfaces (1) introspecção (1) memo (1) oracle (1) reflexão (1)