<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Ramblings &#187; programming</title>
	<atom:link href="http://www.flamingspork.com/blog/tag/programming/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.flamingspork.com/blog</link>
	<description>Ramblings which occasionally resemble reality. This is the blog of Stewart Smith.</description>
	<lastBuildDate>Thu, 29 Jul 2010 22:21:29 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Getting a file size (on Windows)</title>
		<link>http://www.flamingspork.com/blog/2008/02/11/getting-a-file-size-on-windows/</link>
		<comments>http://www.flamingspork.com/blog/2008/02/11/getting-a-file-size-on-windows/#comments</comments>
		<pubDate>Mon, 11 Feb 2008 13:12:08 +0000</pubDate>
		<dc:creator>Stewart Smith</dc:creator>
				<category><![CDATA[Inciting Hatred]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[GetFileSize]]></category>
		<category><![CDATA[GetFileSizeEx]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[win32]]></category>
		<category><![CDATA[windows api]]></category>

		<guid isPermaLink="false">http://www.flamingspork.com/blog/2008/02/11/getting-a-file-size-on-windows/</guid>
		<description><![CDATA[The first point I&#8217;d like to make is that you&#8217;re using a Microsoft Windows API, so you have already lost. You are just not quite aware of how much you have lost. A quick look around and you say &#8220;Ahh&#8230; GetFileSize, that&#8217;s what I want to do!&#8221; Except, of course, you&#8217;re wrong. You don&#8217;t want [...]]]></description>
			<content:encoded><![CDATA[<p>The first point I&#8217;d like to make is that you&#8217;re using a Microsoft Windows API, so you have already lost. You are just not quite aware of how much you have lost.</p>
<p>A quick look around and you say &#8220;Ahh&#8230; GetFileSize, that&#8217;s what I want to do!&#8221; Except, of course, you&#8217;re wrong. You don&#8217;t want to use GetFileSize at all. It has the following signature:</p>
<pre class="code" id="ctl00_rs1_mainContentContainer_ctl02" space="preserve">DWORD WINAPI GetFileSize(  __in       HANDLE <em>hFile</em>,

__out_opt  LPDWORD <em>lpFileSizeHigh</em>

);</pre>
<p>Yes, it supports larger than 4GB files! How? A pointer to the high-order doubleword is passed in!  So how do you know if this errored? Return -1? WRONG! Because the high word could have been set and your file length could legitimately be 0x1ffffffff. So to find out if you actually had an error, you  <strong>must</strong> call  GetLastError! Instead of one call, you now have two.</p>
<p>The Microsoft documentation even acknowledges that this is stupid: &#8220;Because of this behavior, it is recommended that you use      <strong>GetFileSizeEx</strong> instead.&#8221;</p>
<p>GetFileSizeEx is presumably named &#8220;Ex&#8221; as in &#8220;i broke up with my ex because their API sucked.&#8221;</p>
<p>You now have something that looks like this:</p>
<pre class="code" id="ctl00_rs1_mainContentContainer_ctl01" space="preserve">BOOL WINAPI GetFileSizeEx(  __in   HANDLE <em>hFile</em>,

__out  PLARGE_INTEGER <em>lpFileSize</em>

);</pre>
<p>Which starts to look a little bit nicer. For a start, the return code of BOOL seems to indicate success or failure.</p>
<p>You now get to provide a pointer to a LARGE_INTEGER. Which, if you missed it, a LARGE_INTEGER is:</p>
<pre class="code" id="ctl00_rs1_mainContentContainer_ctl02" space="preserve">typedef union _LARGE_INTEGER {  struct {

DWORD LowPart;

LONG HighPart;

};

struct {

DWORD LowPart;

LONG HighPart;

} u;

LONGLONG QuadPart;

} LARGE_INTEGER,

*PLARGE_INTEGER;</pre>
<p>Why this abomination? Well&#8230; &#8221; If your compiler has built-in support for 64-bit integers, use the <strong>QuadPart</strong> member to store the 64-bit integer. Otherwise, use the <strong>LowPart</strong> and <strong>HighPart</strong> members to store the 64-bit integer.&#8221;</p>
<p>That&#8217;s right kiddies&#8230; if you&#8217;ve decided to loose from the get-go and have a compiler that doesn&#8217;t support 64-bit integers, you can still get the file size! Of course, you&#8217;re using a compiler that doesn&#8217;t have 64bit integer support&#8230; and the Microsoft documentation indicates that the GetFileSizeEx call requires Windows 2000&#8230; so it&#8217;s post y2k and you&#8217;re using a compiler without 64-bit ints? You have already lost.</p>
<p>Oh, but you say something about binary compatibility for apps written in the old days (handwave something like that). Well&#8230; let&#8217;s see&#8230; IRIX will give you 64bit numbers in stat (stat64) unless you build with -o32 &#8211; giving you the old ABI. I just can&#8217;t see a use for GetFileSize&#8230;.. somebody please enlighten me.</p>
<p>Which header would you include? Any Linux/UNIX person would think of something logical &#8211; say  sys/stat.h (Linux man page says sys/types.h, sys/stat.h and unistd.h). No, nothing sensible like that. It&#8217;s &#8220;Declared in WinBase.h; include Windows.h&#8221;.</p>
<p>So&#8230; you thought that obviously somebody went through the API and gave you all this Ex function goodness to get rid of mucking about with parts of a 64bit int? You were wrong. Let me say it with this:</p>
<pre class="code" id="ctl00_rs1_mainContentContainer_ctl01" space="preserve">DWORD WINAPI GetCompressedFileSizeTransacted(
  __in       LPCTSTR <em>lpFileName</em>,
  __out_opt  LPDWORD <em>lpFileSizeHigh</em>,
  __in       HANDLE <em>hTransaction</em>
);</pre>
<p>I&#8217;ll now tell you that this was introduced in Vista/Server 2008.</p>
<p>Obviously, you want to be able to use Transaction NTFS on Windows Vista with a compiler that doesn&#8217;t have 64 bit ints. Oh, and you must<strong> </strong>then make another function call to see if something went wrong?</p>
<p>But you know what&#8230; perhaps we can get away from this complete and utter world of madness and use stat()&#8230;. or rather&#8230; perhaps _stati64().</p>
<p>Well&#8230; you&#8217;d be fine except for the fact that these seem to <strong>lie</strong> <strong>to you</strong> (at least on Windows Server 2003 and Vista) &#8211; it seems that even Explorer can lie to you.</p>
<p>But perhaps you&#8217;ve been barking up the wrong tree&#8230; you obviously don&#8217;t want to find the file size at all &#8211; what you want is to FindFirstFile! No, you don&#8217;t want FindFirstFileEx (in this case, Ex is for Extremely complicated). It&#8217;s meant to be faster too&#8230; you know, maybe.</p>
<p>So remember kids, smoke your crack pipe &#8211; you&#8217;re going to need it if using this thing called the Microsoft Windows File Management Functions.</p>


<div class="shr-bookmarks shr-bookmarks-expand shr-bookmarks-center shr-bookmarks-bg-enjoy">
<ul class="socials">
		<li class="shr-facebook">
			<a href="http://www.facebook.com/share.php?v=4&amp;src=bm&amp;u=http://www.flamingspork.com/blog/2008/02/11/getting-a-file-size-on-windows/&amp;t=Getting+a+file+size+%28on+Windows%29" rel="nofollow" class="external" title="Share this on Facebook">Share this on Facebook</a>
		</li>
		<li class="shr-twitter">
			<a href="http://twitter.com/home?status=Getting+a+file+size+%28on+Windows%29+-+http://b2l.me/w8fdr&amp;source=shareaholic" rel="nofollow" class="external" title="Tweet This!">Tweet This!</a>
		</li>
		<li class="shr-delicious">
			<a href="http://delicious.com/post?url=http://www.flamingspork.com/blog/2008/02/11/getting-a-file-size-on-windows/&amp;title=Getting+a+file+size+%28on+Windows%29" rel="nofollow" class="external" title="Share this on del.icio.us">Share this on del.icio.us</a>
		</li>
		<li class="shr-digg">
			<a href="http://digg.com/submit?phase=2&amp;url=http://www.flamingspork.com/blog/2008/02/11/getting-a-file-size-on-windows/&amp;title=Getting+a+file+size+%28on+Windows%29" rel="nofollow" class="external" title="Digg this!">Digg this!</a>
		</li>
		<li class="shr-googlebuzz">
			<a href="http://www.google.com/buzz/post?url=http://www.flamingspork.com/blog/2008/02/11/getting-a-file-size-on-windows/&amp;imageurl=" rel="nofollow" class="external" title="Post on Google Buzz">Post on Google Buzz</a>
		</li>
</ul>
<div style="clear:both;"></div>
</div>

]]></content:encoded>
			<wfw:commentRss>http://www.flamingspork.com/blog/2008/02/11/getting-a-file-size-on-windows/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
