terça-feira, fevereiro 13, 2007

Nova Casa

Para os poucos freqüentadores desse blog segue o novo endereço: http://codebehind.wordpress.com.

[]´s

Thiago

segunda-feira, fevereiro 12, 2007

Problemas com Crystal Reports após instalação do Visual Studio 2005 SP1


Não sei quantos de vocês já tiveram o problema que eu vou descrever agora, mas me parece que ocorreu logo após a instalação do Service Pack 1 do Visual Studio 2005, que pode ser encontrado aqui.

Let´s get down to business.

Após instalar o SP 1 do Visual Studio 2005, fiquei um tempo sem ter que trabalhar em um projeto que usa extensivamente relatórios feitos em Crystal Reports. Semana passada, quando tive que efetuar uma alteração em um dos relatórios desse projeto, abri a solução rodei o projeto e vejam a tela bacaninha que pipocou.



Legal, não?

A única pista que eu tinha até o momento era o bendito CLSID {11BD5260-15B6-412D-80DB-12BB60B8FE50}, abri o regedit e fiz uma procura por esse CLSID, o que me deu uma pista um pouco melhor de quem poderia ser o culpado de toda essa bagunça. Imagem abaixo mostra que esse CLSID se refere á uma biblioteca do Crysta Reports chamada sacommlayer.dll.



Procurei a abençoada da sacommlayer.dll no caminho que estava no Registro, C:\Arquivos de programas\Arquivos comuns\Business Objects\2.7\Bin\, para minha não muita surpresa, a criatura não estava lá. Entrei em uma outra máquina que o Service Pack 1 não tinha sido instalado, e como eu aprendi que tudo na vida só a violência constrói, copiei todas as dlls existentes no diretório onde a sacommlayer.dll se encontrava para a minha máquina.

Tentei acessar novamente a página em que o relatório estava dando problema e dessa vez a página abriu sem problemas. Antes a página que tinha o componente do Crystal Reports nem abria, agora já estava abrindo. Apliquei alguns filtros no relatório e mandei executar e para minha não grande surpresa novamente mais um problema.



Como vocês podem ver pela imagem, por algum motivo na minha super cópia de arquivos de uma máquina para outra, eu devo ter esquecido de incluir essa tal de crpe32.dll. Entrei no diretório C:\Arquivos de programas\Arquivos comuns\Business Objects\2.7\Bin\, e a dll estava lá. Imaginei que aquele não seria o local correto dessa dll, para tirar essa dúvida abri o FileMon e apliquei o filtro para crpe32.dll. Pra minha supresa o FileMon não "pegava" nada, então possivelmente a excessão estava ocorrendo no lado gerenciado da coisa.

Se nós dermos uma olhada na stack trace da última imagem, podemos ver que a excessão foi lançada no construtor da classe CrystalDecisions.CrystalReports.Engine.CRPE. Abrindo o Reflector e tentarmos localizar o assembly CrystalDecisions.CrystalReports.Engine, não será possível. Não sei o motivo, mas para resolver isso tem um jeitinho.

Abra o prompt e navegue até o diretório, %windir%\Assembly\GAC_MSIL\CrystalDecisions
.CrystalReports.Engine\10.2.3600.0__692fbea5521e1304, e lá estará a CrystalDecisions.CrystalReports.Engine.dll. Copie a dll para um outro diretório fora dessa árvore de diretórios e será possível abrir esse assembly pelo Reflector.

Ufa, depois de tudo isso vamos voltar ao nosso problema.

Navegando pelo Reflector será possível ver que existem dois construtores para essa classe, um estático e ou de instancia, abra o construtor estático e veremos a imagem a seguir.



A linha marcada em vermelho chama o método estático CRPE.GetDllPath() que pode ser a nossa fonte de respostas, abrindo o código desse método no Reflector temos o seguinte:



Opa, agora sim hein, parece que esse método "descobre" o caminho da crpe32.dll acessando a seguinte chave no registro HKLM\SOFTWARE\Crystal Decisions\10.2\Crystal Reports e procurando pelo caminho contido no valor CommonFiles, entrando no registro da minha máquina, como mostra a imagem abaixo, não existe o valor CommonFiles.



Daí em diante a coisa foi simples, criei o valor CommonFiles e o defini o caminho C:\Arquivos de programas\Arquivos comuns\Business Objects\2.7\Bin.

Executei novamente o projeto e abri a página que tinha o relatório com problema e agora tudo funciona perfeitamente. :)

Cagamba, que trabalho, mas o importante é que agora está tudo funcionando como era antes, espero que isso tenha ajude alguém.

[]´s

Thiago

terça-feira, outubro 31, 2006

Depois de muito tempo.....


Após muuuito tempo sem postar, resolvi tomar vergonha e tirar a poeira desse bendito blog.

Nesses 4 meses de empresa nova aprendi bastante coisa nova e interessante. Uma delas é como criar um driver mesmo que ele seja só pra dar uma tela azul :). Bem, não pretendo ser um desenvolvedor de drivers, mas sempre é legal conhecer um pouco a respeito.

E claro, apurrinhar o Wanderlão quando ele está fazendo as análises de trojans e afins. :)

Hoje navegando pelo site da Security Focus encontrei um artigo, meio antigo, dividido em 3 partes, bem interessante falando sobre rootkits.

Veja abaixo:

  • Primeira Parte
  • Segunda Parte
  • Terceira Parte

  • Outro artigo interessante que encontrei, é sobre um tópico já bastante falado em discussões sobre desenvolvimento seguro que é o bendito do SQL Injection. Muitos desenvolvedores já ouviram falar, mas muitos também nunca viram um exemplo bacaninha de como ocorre um ataque via SQL Injection, nesse screen cast Rocky Heckmann mostra como efetuar esse tipo de ataque, quais os problemas enfrentados quando se possuí um servidor de banco de dados com permissões de acesso mal configuradas e o porque devemos assinar os assemblies desenvolvidos em .NET.

    Veja abaixo os links para o screen cast e um artigo que demonstra como efetuar SQL Injection.


  • Assembly Hijacking Attack
  • SQL Injection Walkthrough

  • segunda-feira, agosto 28, 2006

    System.Security.SecureString


    Como post inicial, vou falar sobre uma nova classe introduzida no .Net Framework 2.0 a SecureString, localizada no namespace System.Security.


    A SecureString foi desenvolvida para auxiliar os desenvolvedores proteger informações sensíveis enquanto estão em memória.


    Abaixo seguem algumas vantagens da SecureString com relação ao System.String:



    • É possivel ser removida da memória, quando não for mais necessária, utilizando o método Dispose.

    • O valor contido na SecureString é encriptado quando a instancia é inicializada.

    • Não possui membros para inspecionar, comparar ou converter o valor da instancia.

    • É protegida em memória utilizando a DAPI.



    Para ilustrar a utilização da SecureString, criei uma classe chama SecureStringHelper,
    que encapsula o processo de adicionar e obter valores de uma instância da classe SecureString.



    using System;
    using System.Collections.Generic;
    using System.Text;

    using System.Security;
    using System.Runtime.InteropServices;

    namespace SecureStringPost
    {
    /// Classe auxiliar que encapsula a utilização da classe SecureString.
    /// Esta classe precisa ser compilada com a opção /unsafe.
    /// Por utilizar código não seguro.
    public class SecureStringHelper : IDisposable
    {
    private SecureString _secureString;

    /// Cria uma nova instancia da classe SecureStringHelper
    public SecureStringHelper(byte[] buffer)
    {
    this.MakeSecure(buffer);
    }

    /// Protege o buffer passado como parametro
    private unsafe void MakeSecure(byte[] buffer)
    {
    // Obtem o tamanho em chars do buffer.
    int size = Encoding.Default.GetCharCount(buffer);
    // Aloca memória na stack, utilizando método stackalloc,
    // com o tamanho do buffer.
    // Memória alocada utilizando stackalloc fica em memória
    // até o método retornar.
    char* tempChar = stackalloc char[size];

    // Faz um 'pin' do buffer
    fixed (byte* p = buffer)
    {
    // Obtem um ponteiro para um Char*.
    Encoding.Default.GetChars(p, buffer.Length, tempChar, size);
    // Inicializa a classe secure string, passando o Char* e seu tamanho.
    _secureString = new SecureString(tempChar, size);
    // Protege a secure string contra modificações.
    _secureString.MakeReadOnly();
    }
    buffer = null;
    tempChar = null;
    return;
    }

    /// Obtem o valor contido na instancia da secure string.
    ///
    /// Retorna uma instancia da System.String contendo o valor
    /// protegido pela System.Security.SecureString.
    public string GetStringUnsecure()
    {
    IntPtr ptr = IntPtr.Zero;
    string insecure = null;

    try
    {
    // Obtem um ponteiro para um BSTR, onde irá conter
    // o valor desprotegido, que está na na System.Security.SecureString
    ptr = Marshal.SecureStringToBSTR(_secureString);
    // Converte o ponteiro obtido para uma instancia System.String.
    insecure = Marshal.PtrToStringAuto(ptr);
    }
    finally
    {
    // Libera o ponteiro alocado.
    Marshal.FreeBSTR(ptr);
    }

    // retorna uma instancia não segura da string.
    return insecure;
    }

    /// Libera a memória alocada pela SecureStringHelper.
    public void Dispose()
    {
    if (_secureString != null)
    _secureString.Dispose();
    }
    }
    }

    /// Exemplo de como utilizar a classe acima.
    class Program
    {
    static void Main(string[] args)
    {
    string unsecureString = "MINHA STRING NÃO SEGURA";
    byte[] unsecureBuffer = Encoding.Default.GetBytes(unsecureString);

    using (SecureStringHelper helper = new SecureStringHelper(unsecureBuffer))
    {
    Console.WriteLine(helper.GetStringUnsecure());
    }

    Console.ReadLine();
    }
    }


    Bom, espero que tenham gostado do primeiro post.


    Até mais!
    Valeu!