Link to home
Start Free TrialLog in
Avatar of ptrennum
ptrennum

asked on

Trouble Setting the compression Attribute with DeviceIoControl()

I create a folder in my OnInitDialog:
          CreateDirectory("c:\\FolderToCompress",NULL);
Then in an onButonClick event I create a handle to that directory:
          hFile = CreateFile("c:\\FolderToCompress",GENERIC_READ,NULL,NULL,NULL,NULL,NULL);
I then move a file to the directory:
          MoveFile("c:\\untitled1.bmp","c:\\FolderToCompress\\untitled1.bmp");
Then set the compression attribute with deviceIoControl:
          DeviceIoControl(hFile, FSCTL_SET_COMPRESSION, &Format, sizeof(USHORT),
            NULL, 0, &dummy, NULL);

All this works correctly, the folder is created and file moved into it but the folder is not compressed when finished.  There is something that I am obviously missing here and any light on the matter would be greatly appreciated.
Avatar of jkr
jkr
Flag of Germany image

Can you check what 'GetLastError()' reports if 'DeviceIoControl()' returns 'FALSE'?
Avatar of ptrennum
ptrennum

ASKER

GetLastError returns a 6
hFile handle must have read-write access. You have only GENERIC_READ.
That's

//
// MessageId: ERROR_INVALID_HANDLE
//
// MessageText:
//
//  The handle is invalid.
//
#define ERROR_INVALID_HANDLE             6L

Hmm, try to

  hFile = CreateFile("C:\\FolderToCompress",
      GENERIC_ALL,
      0,
      NULL,
      OPEN_EXISTING,
      FILE_ATTRIBUTE_NORMAL,
      NULL);

as I suggested in your last Q or

  hFile = CreateFile("C:\\FolderToCompress",
      GENERIC_ALL,
      0,
      NULL,
      OPEN_EXISTING,
      FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,
      NULL);

if that still  does not work.
>>hFile = CreateFile("C:\\FolderToCompress",
      GENERIC_ALL,
      0,
      NULL,
      OPEN_EXISTING,
      FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,
      NULL);

That worked to a certain degree.  However now the .bmp is not being moved into the folder.

hFile = CreateFile("c:\\FolderToCompress",GENERIC_ALL,
      0,
      NULL,
      OPEN_EXISTING,
      FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,
      NULL);

MoveFile("c:\\untitled1.bmp","c:\\FolderToCompress\\untitled1.bmp");

DWORD dw;

      if(!DeviceIoControl(hFile, FSCTL_SET_COMPRESSION, &Format, sizeof(USHORT),
            NULL, 0, &dummy, NULL))
      {
            dw = GetLastError();
      }

CloseHandle(hFile);

That is how the code looks so far.
Close the directory handle before 'MoveFile()' or specify 'SHARE_ALL' as the 3rd parameter to 'CreateFile()'.
well it works if I close the handle before the move but there is no SHARE_ALL attribute it comes up undefined and if I close the handle before the move then I get the same error 6 with the device Io Control.
I increased the points on this one as it is proving to be more difficult then I imagined at first
Sorry, SHARE_ALL is simply incorrect, my fault - it should be

DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;

But, since closing the handle works, I'd stick with that method.
Ok I got it moving and got the compression attribute set, however the folder is highlighted blue and the size of it is not any smaller then it would be if the file was just sitting in it normally.  In the folder properties it is checked on the compress box but I don't see any difference in size??
>>however the folder is highlighted blue and the size of it is not any smaller then it would be if the file was just sitting in
>>it normally

That is 'normal'. Right-click on the directory and choose 'Properties' - there you should find both 'Size' and 'Size on disk' (or similar).
The size and size on disk are both identical.  2.25mb
Um, I think the problem is

"Directories are not actually compressed by this operation. Rather, the operation sets the default state for files created in the directory to be compressed." (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/base/fsctl_set_compression.asp - "FSCTL_SET_COMPRESSION"). Since 'MoveFile()' does not really create a file in the target folder, you'll need to 'manually' add that flag, e.g.

BOOL MoveAndCompress ( LPCSTR pszSrc, LPCSTR pszDst)
{
   if (!MoveFile(pszSrc,pszDst)) return FALSE;

  HANDLE hFile;
 USHORT Format = COMPRESSION_FORMAT_DEFAULT;
 DWORD dummy;

 hFile = CreateFile(pszDst,
      GENERIC_ALL,
      SHARE_ALL,
      NULL,
      CREATE_ALWAYS,
      FILE_ATTRIBUTE_NORMAL,
      NULL);

 BOOL bRC = DeviceIoControl(hFile, FSCTL_SET_COMPRESSION, &Format, sizeof(USHORT),
NULL, 0, &dummy, NULL);

 CloseHandle(hFile);

  return bRC;
}
If you're going to be storing .bmp files, .zip format isnt a very good compressor of those.  Some .bmp files have just raw RGB triplets, which .zip doesnt "know" about.  Other .bmp formats are already RLE compressed, which doesnt compress very well either.   You might look into converting them to JPEG format files, which are much smaller.

hFile = CreateFile(pszDst,
      GENERIC_ALL,
      FILE_SHARE_READ,
      NULL,
      CREATE_ALWAYS,
      FILE_ATTRIBUTE_NORMAL,
      NULL);

That makes sense however this line in your func blows away the contents of my file.  I'm using a .bmp and after that runs the bmp is blank and 0 kb.
Ooops, that was meant to be

 hFile = CreateFile(pszDst,
     GENERIC_ALL,
     FILE_SHARE_READ,
     NULL,
     OPEN_EXISTING,
     FILE_ATTRIBUTE_NORMAL,
     NULL);
ASKER CERTIFIED SOLUTION
Avatar of jkr
jkr
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
>if ( '.' == * (pszPath + lstrlen ( pszPath) - 1))
                return;

Is this supposed to be a way to check for the "." and ".." directories?


Hmmmmm.........

>>Is this supposed to be a way to check for the "." and ".." directories?

Yup. *YES*, I do know that this is - err - not really the best way, but that code fragment is kinda old (except the modifications).
So what would be a better way to check for those directories?
You could use

if ( !strcmp(pszPath,".") || !strcmp(pszPath,"..")) return;