[Webinar] Streamline your web hosting managementRegister Today

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1255
  • Last Modified:

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.
0
ptrennum
Asked:
ptrennum
  • 10
  • 8
  • 2
  • +1
1 Solution
 
jkrCommented:
Can you check what 'GetLastError()' reports if 'DeviceIoControl()' returns 'FALSE'?
0
 
ptrennumAuthor Commented:
GetLastError returns a 6
0
 
AlexFMCommented:
hFile handle must have read-write access. You have only GENERIC_READ.
0
Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

 
jkrCommented:
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.
0
 
ptrennumAuthor Commented:
>>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.
0
 
jkrCommented:
Close the directory handle before 'MoveFile()' or specify 'SHARE_ALL' as the 3rd parameter to 'CreateFile()'.
0
 
ptrennumAuthor Commented:
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.
0
 
ptrennumAuthor Commented:
I increased the points on this one as it is proving to be more difficult then I imagined at first
0
 
jkrCommented:
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.
0
 
ptrennumAuthor Commented:
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??
0
 
jkrCommented:
>>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).
0
 
ptrennumAuthor Commented:
The size and size on disk are both identical.  2.25mb
0
 
jkrCommented:
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;
}
0
 
grg99Commented:
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.

0
 
ptrennumAuthor Commented:
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.
0
 
jkrCommented:
Ooops, that was meant to be

 hFile = CreateFile(pszDst,
     GENERIC_ALL,
     FILE_SHARE_READ,
     NULL,
     OPEN_EXISTING,
     FILE_ATTRIBUTE_NORMAL,
     NULL);
0
 
jkrCommented:
BTW, to compress an existing directory tree, you could use a variation of

#include <windows.h>
#include <stdio.h>

void HandleFile ( WIN32_FIND_DATA* pw32fd);
void CompressTree ( char* pszPath,  char*   pszBase);
void main ( int argc, char** argv)
{
    if  (   argc    !=  2)  return;

    CompressTree ( *( argv + 1),    NULL);
}

void CompressTree ( char* pszPath,  char*   pszBase)
{
WIN32_FIND_DATA w32fd;
HANDLE hFind;
DWORD dwAtt;
char acPath [ MAX_PATH];
char acBase [ MAX_PATH];

printf  (   "CheckFiles():\tcalled with '%s' '%s'\n",   pszPath,    pszBase);

if ( '.' == * (pszPath + lstrlen ( pszPath) - 1))
                return;

if  (   pszBase)
    sprintf (   acPath, "%s\\%s",   pszBase,    pszPath);
else
    lstrcpy ( acPath, pszPath);

printf ( "path is %s\n",    acPath);
lstrcpy ( acBase, acPath);

dwAtt = GetFileAttributes ( acPath);

if ( 0xffffffff == dwAtt)
{
 // error ...
}

if ( FILE_ATTRIBUTE_DIRECTORY & dwAtt)
{
    if  (   '\\'    ==  acPath  [   lstrlen (   acPath) -   1])
            lstrcat (   acPath, "*.*");
     else
            lstrcat (   acPath, "\\*.*");

    printf ( "path is now %s\n",    acPath);
}


hFind = FindFirstFile ( acPath, &w32fd);

if ( INVALID_HANDLE_VALUE == hFind)
{
 // error

printf ( "ERROR %d\n",  GetLastError    ());

return;
}

// recurse if directory...
if ( FILE_ATTRIBUTE_DIRECTORY == w32fd.dwFileAttributes)
{

     CompressTree ( w32fd.cFileName,    acBase);
}
else
 HandleFile ( &w32fd);

while ( FindNextFile ( hFind, &w32fd))
{
    // recurse if directory...
    if ( FILE_ATTRIBUTE_DIRECTORY == w32fd.dwFileAttributes)
    {

     CompressTree ( w32fd.cFileName,    acBase);
    }
    else
      HandleFile ( &w32fd);
}

if ( ERROR_NO_MORE_FILES != GetLastError())
{
 // error
}
FindClose ( hFind);
}

void HandleFile ( WIN32_FIND_DATA* pw32fd)
{
HANDLE hFile;
USHORT Format = COMPRESSION_FORMAT_DEFAULT;
DWORD dummy;

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

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

CloseHandle(hFile);
}
0
 
grg99Commented:
>if ( '.' == * (pszPath + lstrlen ( pszPath) - 1))
                return;

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


Hmmmmm.........

0
 
jkrCommented:
>>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).
0
 
ptrennumAuthor Commented:
So what would be a better way to check for those directories?
0
 
jkrCommented:
You could use

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

0

Featured Post

Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

  • 10
  • 8
  • 2
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now