• [Funcion] RtlCompressBuffer c++

 #477519  por crack81
 07 Sep 2015, 04:45
Buscando en mis codigos encontre este ejemplo de como usar la RtlCompressBuffer tanto como para comprimir como para descomprimir en un principio la funcion estaba diseñada funcion en el C clasico por eso por el uso excesivo de punteros despues termine complementadolo con c++ asi que quedo como un revoltijo c y c++ XD
Pero se puede retocar facilmente y si no le gusta el uso de *Char pueden usar string por comodidad
#include <iostream>
#include <windows.h>
using namespace std;


typedef unsigned long NTSTATUS;

#define STATUS_SUCCESS                 ((NTSTATUS)0x00000000UL)
#define STATUS_BUFFER_ALL_ZEROS        ((NTSTATUS)0x00000117UL)
#define STATUS_INVALID_PARAMETER       ((NTSTATUS)0xC000000DUL)
#define STATUS_UNSUPPORTED_COMPRESSION ((NTSTATUS)0xC000025FUL)
#define STATUS_NOT_SUPPORTED_ON_SBS    ((NTSTATUS)0xC0000300UL)
#define STATUS_BUFFER_TOO_SMALL        ((NTSTATUS)0xC0000023UL)
#define STATUS_BAD_COMPRESSION_BUFFER  ((NTSTATUS)0xC0000242UL)

HMODULE ntdll = GetModuleHandle("ntdll.dll");

typedef NTSTATUS(__stdcall *_RtlCompressBuffer)(
   USHORT CompressionFormatAndEngine,
   PUCHAR UncompressedBuffer,
   ULONG UncompressedBufferSize,
   PUCHAR CompressedBuffer,
   ULONG CompressedBufferSize,
   ULONG UncompressedChunkSize,
   PULONG FinalCompressedSize,
   PVOID WorkSpace
);

typedef NTSTATUS(__stdcall *_RtlDecompressBuffer)(
   USHORT CompressionFormat,
   PUCHAR UncompressedBuffer,
   ULONG UncompressedBufferSize,
   PUCHAR CompressedBuffer,
   ULONG CompressedBufferSize,
   PULONG FinalUncompressedSize
);

typedef NTSTATUS(__stdcall *_RtlGetCompressionWorkSpaceSize)(
   USHORT CompressionFormatAndEngine,
   PULONG CompressBufferWorkSpaceSize,
   PULONG CompressFragmentWorkSpaceSize
);

char *ReadFileWs(const char *FilePath,DWORD &bufferLen){
    HANDLE File=CreateFileA(FilePath,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);

    if(File==INVALID_HANDLE_VALUE){
        return NULL;
    }

    DWORD _size=GetFileSize(File,0);
    char *Buffer=new char[_size+1];
    bool result=ReadFile(File,Buffer,_size,&bufferLen,0);
    CloseHandle(File);

    if(result)return Buffer;
    else return NULL;
}

bool WriteFileWs(const char *FilePath,char *Buffer,DWORD bufferLen,DWORD &numberBytesRead){
    HANDLE File=CreateFileA(FilePath,GENERIC_WRITE,FILE_SHARE_WRITE,0,CREATE_ALWAYS,0,0);

    if(File==INVALID_HANDLE_VALUE){
        return false;
    }

    bool result=WriteFile(File,Buffer,bufferLen,&numberBytesRead,NULL);
    CloseHandle(File);

    return result;
}


UCHAR *compress_buffer(const char *buffer, const ULONG bufferLen, ULONG compBufferLen, ULONG *compBufferSize)
{
   _RtlCompressBuffer RtlCompressBuffer = (_RtlCompressBuffer) GetProcAddress(ntdll, "RtlCompressBuffer");
   _RtlGetCompressionWorkSpaceSize RtlGetCompressionWorkSpaceSize = (_RtlGetCompressionWorkSpaceSize) GetProcAddress(ntdll, "RtlGetCompressionWorkSpaceSize");

   ULONG bufWorkspaceSize;  // Workspace Size
   ULONG fragWorkspaceSize; // Fragmented Workspace Size (Unused)
   NTSTATUS ret = RtlGetCompressionWorkSpaceSize(
                     COMPRESSION_FORMAT_LZNT1 | COMPRESSION_ENGINE_MAXIMUM, // CompressionFormatAndEngine
                     &bufWorkspaceSize,                                     // CompressBufferWorkSpaceSize
                     &fragWorkspaceSize                                     // CompressFragmentWorkSpaceSize
                  );

   if (ret != STATUS_SUCCESS) return 0;

   VOID *workspace = (VOID *)LocalAlloc(LMEM_FIXED, bufWorkspaceSize);
   if (workspace == NULL) return 0;

   UCHAR *compBuffer = new UCHAR[compBufferLen];
   NTSTATUS result = RtlCompressBuffer(
                        COMPRESSION_FORMAT_LZNT1 | COMPRESSION_ENGINE_MAXIMUM, // CompressionFormatAndEngine
                        (UCHAR *)buffer,                                       // UncompressedBuffer
                        bufferLen,                                             // UncompressedBufferSize
                        compBuffer,                                            // CompressedBuffer
                        compBufferLen,                                         // CompressedBufferSize
                        4096,                                                  // UncompressedChunkSize
                        compBufferSize,                                        // FinalCompressedSize
                        workspace                                              // WorkSpace
                     );

   LocalFree(workspace);
   if (result != STATUS_SUCCESS) {
        return 0;
   }

   return compBuffer;
}

UCHAR *decompress_buffer(const char *buffer, const int bufferLen, const int uncompBufferLen, ULONG *uncompBufferSize)
{
   _RtlDecompressBuffer RtlDecompressBuffer = (_RtlDecompressBuffer) GetProcAddress(ntdll, "RtlDecompressBuffer");

   UCHAR *uncompBuffer = new UCHAR[uncompBufferLen];
   NTSTATUS result = RtlDecompressBuffer(
                        COMPRESSION_FORMAT_LZNT1 | COMPRESSION_ENGINE_MAXIMUM, // CompressionFormat
                        uncompBuffer,                                          // UncompressedBuffer
                        uncompBufferLen,                                       // UncompressedBufferSize
                        (UCHAR *)buffer,                                       // CompressedBuffer
                        bufferLen,                                             // CompressedBufferSize
                        uncompBufferSize                                       // FinalUncompressedSize
                     );

   if (result != STATUS_SUCCESS) {;
      return 0;
   }


   return uncompBuffer;
}


int main(void)
{
  char *path=(char*)"C:\\bcb6kg.exe";//archivo original a ser comprimido y descomprimido
  char *NewPath=(char*)"C:\\Nuevo.exe";//la nueva ruta del comprimido
  char *DecompressPath=(char*)"C:\\descomprimido.exe";//la nueva ruta del comprimido
  DWORD bufferLen,numberBytesRead,compBufferSize,realDecompSize;

  char *data=ReadFileWs(path,bufferLen);//necesitara ser liberado
  UCHAR *bufferComprimido=compress_buffer(data,bufferLen,bufferLen+512,&compBufferSize);//necesitara ser liberado
  cout<<"Archivo Leido y comprimido"<<endl;

  WriteFileWs(NewPath,(char*)bufferComprimido,compBufferSize,numberBytesRead);
  cout<<"Archivo comprimido escrito en la ruta indicada"<<endl;

  UCHAR *bufferDescomprimido=decompress_buffer((char*)bufferComprimido,bufferLen,compBufferSize*100,&realDecompSize);
  WriteFileWs(DecompressPath,(char*)bufferDescomprimido,bufferLen,numberBytesRead);
  cout<<"Archivo descomprimido y escrito en la ruta indicada "<<endl;

  delete[] data;//liberamos
  delete[] bufferComprimido;
  delete[] bufferDescomprimido;



  cin.get();
  return 0;
}
Saludos..
 #477520  por Blau
 07 Sep 2015, 05:44
¿Cuál es el resultado?, ¿cuánta es la diferencia de peso entre archivos? No tengo ganas de comprobarlo