10

I am trying to debug a program that manipulates a file. For example, I set the file-pointer to offset 4 (using a base of 0), but it seems to be starting at offset 5 instead.

To try to figure out what is happening, I want to put in a line to print out the current file pointer (I’m not using an IDE for this little project, just Notepad2 and the command-line). Unfortunately there does not seem to be a Windows API function to retrieve the current file pointer, only one to set it.

I’m recall being able to find the current file pointer in Pascal (in DOS), but how can the current file pointer be determined in C++ in Windows?

Synetech
  • 9,643
  • 9
  • 64
  • 96
  • (For the record, it turned out that it was working correctly; I was just using the wrong test file. After I finished testing the size-based mode, I started testing the offset-based mode and forgot to start using the offset-based test file instead of the size-based test file. Doh! `›_‹`) – Synetech Jul 17 '13 at 18:24

1 Answers1

21

Unlike most functions, that provide both a getter and setter (in the read-write sense), there is indeed no GetFilePointer or GetFilePointerEx.

However the value can be retrieved by calling SetFilePointer(Ex). The two SetFilePointer functions return the the return/output from SetFilePointer, but you have to make sure to specify an offset of 0, and FILE_CURRENT as the mode. That way, it moves 0 bytes from where it is, then returns (I can’t vouch for whether or not it wastes CPU cycles and RAM to perform the zero-move, but I would think they have optimized to not do so).

Yes, it is inconsistent and confusing (and redundant and poorly designed), but you can wrap it in your own GetFilePointer(Ex) function:

DWORD    GetFilePointer   (HANDLE hFile) {
    return SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
}


LONGLONG GetFilePointerEx (HANDLE hFile) {
    LARGE_INTEGER liOfs={0};
    LARGE_INTEGER liNew={0};
    SetFilePointerEx(hFile, liOfs, &liNew, FILE_CURRENT);
    return liNew.QuadPart;
}
Synetech
  • 9,643
  • 9
  • 64
  • 96
  • 1
    Neither of your implementations contain error handling. The first one silently fails for files larger than 4GB. Neither one is desirable. – IInspectable Jan 12 '17 at 19:28
  • There are many cases where you know in advance that the file will NEVER be longer than 4 GB. In this case the code is OK. – Elmue Nov 18 '20 at 22:07
  • Besides, this wasn't production code, it was just a sample for answering the specific question. Error handling is left as an exercise for the reader. – Synetech Nov 19 '20 at 23:14
  • @IInspectable, what is wrong with the second implementation, other than not checking for `SetFilePointerEx` return status? – Violet Giraffe Feb 08 '23 at 08:46
  • @VioletGiraffe If the [`SetFilePointerEx`](https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-setfilepointerex) API call fails, the value returned through `lpNewFilePointer` is *indeterminate*. It could be anything, but the code moves on to just return it, unconditionally, thereby promoting invalid data to reliable data. A corollary of this is that now every client using `GetFilePointerEx` is broken, too. – IInspectable Feb 08 '23 at 09:54
  • @Elmue Even in that case (which I will challenge will hold over time) it's just negligent to not be prepared for file sizes 4GB and up. [`SetFilePointer`](https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-setfilepointer) already returns this information. So you've performed the expensive operation (the function call), and then just waste it all by not caring. A non-truncating implementation is very likely just as fast. – IInspectable Feb 08 '23 at 10:10
  • @IInspectable: understood, that I did fix in my code immediately upon copying from here. Thanks for the detailed clarification. Why wouldn't you edit the answer and add the missing condition? You could return `-1` on failure, for instance. – Violet Giraffe Feb 08 '23 at 19:19