[Win32utils-devel] win32-file, overlapped added

win32utils-devel at rubyforge.org win32utils-devel at rubyforge.org
Mon Nov 22 19:26:00 EST 2004


Hi,
> 
> > The problem is due to ReadFile cannot read large file at one 
> > call in case of larger than 0x3000000 bytes with 
> > NO_BUFFERING. I tested using while loop and it works. Just 
> > borrow some code from it again.:)
> 
> I must be dense, because even if I try to use that option on a small
> file, I get "the parameter is incorrect".  What am I missing?
> 
> Dan
> 
Here is my test code for case NO_BUFFERING:

int getsectorcount(int x,char* str) { /*a function that returns number of sectors in file*sectorsize */
DWORD y[4];
if(GetDiskFreeSpace(str,&y[0],&y[1],&y[2],&y[3])==0)
      rb_raise(cFileError,ErrorDescription(GetLastError()));
y[0]=x%y[1];
if(y[0]!=0)x+=y[1]-y[0];
return x;
}

/*
 * Uses the native ReadFile() behind the scenes.
 */
static VALUE file_nread(int argc, VALUE* argv, VALUE self){
   OVERLAPPED olap;
   OpenFile *fptr;
   int fd;
   BOOL rv;
   HANDLE hFile;
   DWORD dwBytesToRead, dwBytesRead;
   int dwToRead, dwRead;
   VALUE rbLength, rbOffset, rbBuffer;
   char* lpBuffer = NULL;
   char* lpPtr = NULL;
   VALUE rbPath;
   char lpPath[256];
   rbPath = file_get_path(self);
   strcpy(lpPath,StringValuePtr(rbPath));
   lpPath[3] = 0;

   rb_scan_args(argc,argv,"02",&rbLength,&rbOffset);

   GetOpenFile(self, fptr);
   fd = _fileno(fptr->f);
   hFile = (HANDLE)_get_osfhandle(fd);

   memset(&olap, 0, sizeof(OVERLAPPED));

   olap.Offset     = 0;
   olap.OffsetHigh = 0;
   olap.hEvent     = NULL; // TODO: Allow Win32::Event object

   if(Qnil != rbOffset)
      olap.Offset = NUM2INT(rbOffset);

   if(hFile == INVALID_HANDLE_VALUE)
      rb_raise(cFileError,ErrorDescription(GetLastError()));

   if(NIL_P(rbLength)){
      dwBytesToRead = GetFileSize(hFile,NULL);
   }
   else{
      dwBytesToRead = NUM2UINT(rbLength);
   }
   lpBuffer = malloc(getsectorcount(dwBytesToRead,lpPath));
   memset(lpBuffer,0x00,dwBytesToRead);
   if(NULL == lpBuffer)
      rb_raise(cFileError,"malloc() call failed in nread() method");
lpPtr = lpBuffer;
dwRead = 0;
dwToRead = getsectorcount(dwBytesToRead,lpPath);
if(dwBytesToRead>0x1000000)
while(dwToRead>0) {
   if(dwToRead>0x1000000)
   rv = ReadFile(
      hFile,
      (LPVOID)lpPtr,
        0x1000000,
      &dwRead,
      &olap
   );
   else
   rv = ReadFile(
      hFile,
      (LPVOID)lpPtr,
       dwToRead,
      &dwRead,
      &olap
   );
   if(0 == rv)
      rb_raise(cFileError,ErrorDescription(GetLastError()));
   lpPtr += 0x1000000;
   dwToRead -= 0x1000000;
   dwBytesRead += dwRead;
}
else
{
   rv = ReadFile(
      hFile,
      (LPVOID)lpPtr,
        dwToRead,
      &dwBytesRead,
      &olap
   );
   if(0 == rv)
      rb_raise(cFileError,ErrorDescription(GetLastError()));
}

   if(dwBytesToRead != dwBytesRead)
      rb_raise(cFileError,"bytes to read != bytes actually read");

   // This exchange is necessary so that we don't have a memory leak (I think)

   rbBuffer = rb_str_new(lpBuffer,dwBytesRead);

   free(lpBuffer);
   return rbBuffer;
}


Regards,

Park Heesob



--MIME Multi-part separator--



More information about the win32utils-devel mailing list