【发布时间】:2010-10-31 16:33:12
【问题描述】:
我们有一行代码
if( !CreateFile( m_hFile, szFile, GENERIC_READ|GENERIC_WRITE, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL ) )
{
DWORD dwErr = GetLastError();
CString czInfo;
czInfo.Format ("CMemoryMapFile::OpenAppend SetFilePointer call failed - GetLastError returned %d", dwErr);
LOG(czInfo);
return false;
}
此代码多年来一直运行良好。几周前,我们有一个客户遇到了问题。事实证明,问题可以追溯到这行代码,其中函数将返回一个 INVALID_HANDLE_VALUE 句柄,而 GetLastError() 返回 ERROR_FILE_NOT_FOUND(2)。
现在,这让我们非常困惑。如果文件不存在,则 OPEN_ALWAYS 应该指示要创建的文件。那么,为什么我们会收到 ERROR_FILE_NOT_FOUND?
更多困惑:对于这位客户,这只发生在一个网络共享点上(我们使用的是 UNC 路径)。此客户的其他机器的其他 UNC 路径有效。本地路径有效。我们所有其他客户(安装超过 10000 次)都没有问题。
客户使用 XP 作为客户端操作系统,而服务器运行的似乎是标准的 Windows Server 2003(我认为是 Small Business Server 版本)。我们无法在使用相同操作系统的测试实验室中复制他们的错误。他们可以在多个 XP 客户端上重复该问题,但问题仅出现在一台服务器上(其他 Server 2003 服务器没有出现此问题)。
我们通过嵌套两个 CreateFile 调用解决了这个问题,第一个调用 OPEN_EXISTING,如果 OPEN_EXISTING 失败,第二个调用 CREATE_ALWAYS。因此,我们没有立即修复的需要。
我的问题:有谁知道为什么这个 API 调用会以这种特殊方式失败?我们很困惑。
附录:
上面的 CreateFile 函数是 Windows API 函数的封装。代码如下:
bool CMemoryMapFile::CreateFile( HANDLE & hFile, LPCSTR szFile, DWORD dwDesiredAccess, DWORD dwShareMode, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes )
{
hFile = ::CreateFile (szFile, dwDesiredAccess, dwShareMode, NULL,
dwCreationDisposition, dwFlagsAndAttributes, NULL);
return (hFile != INVALID_HANDLE_VALUE)
}
【问题讨论】:
-
一些用户非常有帮助地注意到我们假设 CreateFile 在失败时返回一个 NULL 句柄。我忘了(mea culpa)提到上面示例中的 CreateFile 实际上是一个包装函数。我将包装函数添加到我上面的问题中。包装器返回一个布尔值。