?
Solved

Trouble Setting the compression Attribute with DeviceIoControl()

Posted on 2005-03-01
21
Medium Priority
?
1,213 Views
Last Modified: 2012-08-14
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
Comment
Question by:ptrennum
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 10
  • 8
  • 2
  • +1
21 Comments
 
LVL 86

Expert Comment

by:jkr
ID: 13431649
Can you check what 'GetLastError()' reports if 'DeviceIoControl()' returns 'FALSE'?
0
 

Author Comment

by:ptrennum
ID: 13431697
GetLastError returns a 6
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 13431758
hFile handle must have read-write access. You have only GENERIC_READ.
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 86

Expert Comment

by:jkr
ID: 13431782
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
 

Author Comment

by:ptrennum
ID: 13431877
>>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
 
LVL 86

Expert Comment

by:jkr
ID: 13431921
Close the directory handle before 'MoveFile()' or specify 'SHARE_ALL' as the 3rd parameter to 'CreateFile()'.
0
 

Author Comment

by:ptrennum
ID: 13432005
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
 

Author Comment

by:ptrennum
ID: 13432018
I increased the points on this one as it is proving to be more difficult then I imagined at first
0
 
LVL 86

Expert Comment

by:jkr
ID: 13432101
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
 

Author Comment

by:ptrennum
ID: 13432104
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
 
LVL 86

Expert Comment

by:jkr
ID: 13432150
>>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
 

Author Comment

by:ptrennum
ID: 13432175
The size and size on disk are both identical.  2.25mb
0
 
LVL 86

Expert Comment

by:jkr
ID: 13432421
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
 
LVL 22

Expert Comment

by:grg99
ID: 13432554
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
 

Author Comment

by:ptrennum
ID: 13432788
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
 
LVL 86

Expert Comment

by:jkr
ID: 13432830
Ooops, that was meant to be

 hFile = CreateFile(pszDst,
     GENERIC_ALL,
     FILE_SHARE_READ,
     NULL,
     OPEN_EXISTING,
     FILE_ATTRIBUTE_NORMAL,
     NULL);
0
 
LVL 86

Accepted Solution

by:
jkr earned 2000 total points
ID: 13432864
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
 
LVL 22

Expert Comment

by:grg99
ID: 13433074
>if ( '.' == * (pszPath + lstrlen ( pszPath) - 1))
                return;

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


Hmmmmm.........

0
 
LVL 86

Expert Comment

by:jkr
ID: 13435750
>>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
 

Author Comment

by:ptrennum
ID: 13439182
So what would be a better way to check for those directories?
0
 
LVL 86

Expert Comment

by:jkr
ID: 13440464
You could use

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

0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
Introduction This article is the first in a series of articles about the C/C++ Visual Studio Express debugger.  It provides a quick start guide in using the debugger. Part 2 focuses on additional topics in breakpoints.  Lastly, Part 3 focuses on th…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.
Suggested Courses
Course of the Month9 days, 22 hours left to enroll

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question