blez
blez

Reputation: 5047

DuplicateHandle for a file

I'm trying to make DuplicateHandle() for a file that another process writes. I succeeded, but I get the position of the owner process. After I seek to the beginning it seeks also in the owner process. Can I somehow seek without changing the first process's progress?

EDIT:

Another application opens this file without CreateFile. Is thare a way to read the file form the begining with ReadFile, without seeking manually?

EDIT again:

There isn't a way to read only from one side with duplicated handle. Thanks for helping.

Upvotes: 0

Views: 3157

Answers (2)

ixe013
ixe013

Reputation: 10191

Instead of DuplicateHandle, you must call CreateFile in both process, with the right combination of access mode and sharing flag. MSDN has the full set of rules, here is a combination that works :

Writer process :

 HANDLE file = CreateFile(..., GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, ...);

Reader process :

 HANDLE file = CreateFile(..., GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, ...);

If you need to play with the flags, here is the (crude) test application I wrote to answer your question :

 // 2process1file.cpp : Defines the entry point for the console application.
 //

 #include "stdafx.h"
 #include <Windows.h>
 #include <stdio.h>
 #include <tchar.h>

 #define NUMBER_OF_LINES 100
 #define IO_PERIOD 250
 static const char message[] = "The quick brown fox jumps over the lazy dog.\n";

 HANDLE file = INVALID_HANDLE_VALUE;

 BOOL CtrlHandler(DWORD ctltype)
 {
     if(file != INVALID_HANDLE_VALUE) 
     {
         CloseHandle(file);
         file = INVALID_HANDLE_VALUE;
     }

     return FALSE;
 }

 int _tmain(int argc, _TCHAR* argv[])
 {
     if(argc == 3) 
     {
         DWORD access = GENERIC_READ;
         DWORD share = FILE_SHARE_READ;
         bool is_writer = false;

         if((*argv[1]|' ') == 'w')
         {
             access |= GENERIC_WRITE;
             is_writer = true;
         }
         else
         {
             share |= FILE_SHARE_WRITE;
         }

         file = CreateFile(argv[2], access, share, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);

         if(file != INVALID_HANDLE_VALUE)
         {
             DWORD nbytes = 1;

             SetFilePointer(file, 0, 0, FILE_BEGIN); //Redundant when writing

             for(int i=0; (i<NUMBER_OF_LINES) && nbytes; ++i) {
                 if(is_writer) {
                     if(WriteFile(file, message, sizeof(message)-1, &nbytes, 0) == 0)
                     {
                         //Write failed somehow
                         break;
                     }

                     //Sleep(INFINITE);

                     if(i%25 == 0) printf("%d\n", i); 
                 } else {
                     char buffer[sizeof message] = "";

                     if(ReadFile(file, buffer, sizeof(buffer)-1, &nbytes, 0) && nbytes) {
                         buffer[sizeof(buffer)-1] = 0;
                         printf(buffer);
                     } else {
                         //Read failed somehow
                         break;
                     }
                 }

                 Sleep(IO_PERIOD);
             }

             CloseHandle(file);
             file = INVALID_HANDLE_VALUE;
         }
     }
     else
     {
         wprintf(L"Usage : %s [w|r] filename\n");
     }

     return 0;
 }

Upvotes: 2

Chad
Chad

Reputation: 19052

From MSDN:

The duplicate handle refers to the same object as the original handle. Therefore, any changes to the object are reflected through both handles. For example, if you duplicate a file handle, the current file position is always the same for both handles. For file handles to have different file positions, use the CreateFile function to create file handles that share access to the same file.

Upvotes: 5

Related Questions