scrrun: Implement ReadAll().

This commit is contained in:
Nikolay Sivov 2014-04-03 17:34:25 +04:00 committed by Alexandre Julliard
parent ec3417e290
commit c927336c5a
4 changed files with 256 additions and 14 deletions

View File

@ -37,6 +37,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(scrrun); WINE_DEFAULT_DEBUG_CHANNEL(scrrun);
static const WCHAR bsW[] = {'\\',0}; static const WCHAR bsW[] = {'\\',0};
static const WCHAR utf16bom = 0xfeff;
struct foldercollection { struct foldercollection {
IFolderCollection IFolderCollection_iface; IFolderCollection IFolderCollection_iface;
@ -110,7 +111,7 @@ struct textstream {
IOMode mode; IOMode mode;
BOOL unicode; BOOL unicode;
BOOL first_write; BOOL first_read;
LARGE_INTEGER size; LARGE_INTEGER size;
HANDLE file; HANDLE file;
}; };
@ -374,23 +375,114 @@ static HRESULT WINAPI textstream_Read(ITextStream *iface, LONG len, BSTR *text)
static HRESULT WINAPI textstream_ReadLine(ITextStream *iface, BSTR *text) static HRESULT WINAPI textstream_ReadLine(ITextStream *iface, BSTR *text)
{ {
struct textstream *This = impl_from_ITextStream(iface); struct textstream *This = impl_from_ITextStream(iface);
VARIANT_BOOL eos;
HRESULT hr;
FIXME("(%p)->(%p): stub\n", This, text); FIXME("(%p)->(%p): stub\n", This, text);
if (!text)
return E_POINTER;
*text = NULL;
if (textstream_check_iomode(This, IORead)) if (textstream_check_iomode(This, IORead))
return CTL_E_BADFILEMODE; return CTL_E_BADFILEMODE;
/* check for EOF */
hr = ITextStream_get_AtEndOfStream(iface, &eos);
if (FAILED(hr))
return hr;
if (eos == VARIANT_TRUE)
return CTL_E_ENDOFFILE;
return E_NOTIMPL; return E_NOTIMPL;
} }
static HRESULT WINAPI textstream_ReadAll(ITextStream *iface, BSTR *text) static HRESULT WINAPI textstream_ReadAll(ITextStream *iface, BSTR *text)
{ {
struct textstream *This = impl_from_ITextStream(iface); struct textstream *This = impl_from_ITextStream(iface);
FIXME("(%p)->(%p): stub\n", This, text); LARGE_INTEGER start, end, dist;
DWORD toread, read;
HRESULT hr;
char *buff;
BOOL ret;
TRACE("(%p)->(%p)\n", This, text);
if (!text)
return E_POINTER;
*text = NULL;
if (textstream_check_iomode(This, IORead)) if (textstream_check_iomode(This, IORead))
return CTL_E_BADFILEMODE; return CTL_E_BADFILEMODE;
return E_NOTIMPL; if (!This->first_read) {
VARIANT_BOOL eos;
/* check for EOF */
hr = ITextStream_get_AtEndOfStream(iface, &eos);
if (FAILED(hr))
return hr;
if (eos == VARIANT_TRUE)
return CTL_E_ENDOFFILE;
}
/* read everything from current position */
dist.QuadPart = 0;
SetFilePointerEx(This->file, dist, &start, FILE_CURRENT);
SetFilePointerEx(This->file, dist, &end, FILE_END);
toread = end.QuadPart - start.QuadPart;
/* rewind back */
dist.QuadPart = start.QuadPart;
SetFilePointerEx(This->file, dist, NULL, FILE_BEGIN);
This->first_read = FALSE;
if (toread == 0) {
*text = SysAllocStringLen(NULL, 0);
return *text ? S_FALSE : E_OUTOFMEMORY;
}
if (toread < sizeof(WCHAR))
return CTL_E_ENDOFFILE;
buff = heap_alloc(toread);
if (!buff)
return E_OUTOFMEMORY;
ret = ReadFile(This->file, buff, toread, &read, NULL);
if (!ret || toread != read) {
WARN("failed to read from file %d, %d, error %d\n", read, toread, GetLastError());
heap_free(buff);
return E_FAIL;
}
hr = S_FALSE;
if (This->unicode) {
int i = 0;
/* skip BOM */
if (start.QuadPart == 0 && *(WCHAR*)buff == utf16bom) {
read -= sizeof(WCHAR);
i += sizeof(WCHAR);
}
*text = SysAllocStringLen(read ? (WCHAR*)&buff[i] : NULL, read/sizeof(WCHAR));
if (!*text) hr = E_OUTOFMEMORY;
}
else {
INT len = MultiByteToWideChar(CP_ACP, 0, buff, read, NULL, 0);
*text = SysAllocStringLen(NULL, len);
if (*text)
MultiByteToWideChar(CP_ACP, 0, buff, read, *text, len);
else
hr = E_OUTOFMEMORY;
}
heap_free(buff);
return hr;
} }
static HRESULT textstream_writestr(struct textstream *stream, BSTR text) static HRESULT textstream_writestr(struct textstream *stream, BSTR text)
@ -399,15 +491,6 @@ static HRESULT textstream_writestr(struct textstream *stream, BSTR text)
BOOL ret; BOOL ret;
if (stream->unicode) { if (stream->unicode) {
if (stream->first_write) {
static const WCHAR utf16bom = 0xfeff;
DWORD written = 0;
BOOL ret = WriteFile(stream->file, &utf16bom, sizeof(utf16bom), &written, NULL);
if (!ret || written != sizeof(utf16bom))
return create_error(GetLastError());
stream->first_write = FALSE;
}
ret = WriteFile(stream->file, text, SysStringByteLen(text), &written, NULL); ret = WriteFile(stream->file, text, SysStringByteLen(text), &written, NULL);
return (ret && written == SysStringByteLen(text)) ? S_OK : create_error(GetLastError()); return (ret && written == SysStringByteLen(text)) ? S_OK : create_error(GetLastError());
} else { } else {
@ -555,7 +638,7 @@ static HRESULT create_textstream(const WCHAR *filename, DWORD disposition, IOMod
stream->ref = 1; stream->ref = 1;
stream->mode = mode; stream->mode = mode;
stream->unicode = unicode; stream->unicode = unicode;
stream->first_write = TRUE; stream->first_read = TRUE;
stream->file = CreateFileW(filename, access, 0, NULL, disposition, FILE_ATTRIBUTE_NORMAL, NULL); stream->file = CreateFileW(filename, access, 0, NULL, disposition, FILE_ATTRIBUTE_NORMAL, NULL);
if (stream->file == INVALID_HANDLE_VALUE) if (stream->file == INVALID_HANDLE_VALUE)
@ -570,6 +653,16 @@ static HRESULT create_textstream(const WCHAR *filename, DWORD disposition, IOMod
else else
stream->size.QuadPart = 0; stream->size.QuadPart = 0;
/* Write Unicode BOM */
if (unicode && mode == ForWriting && (disposition == CREATE_ALWAYS || disposition == CREATE_NEW)) {
DWORD written = 0;
BOOL ret = WriteFile(stream->file, &utf16bom, sizeof(utf16bom), &written, NULL);
if (!ret || written != sizeof(utf16bom)) {
ITextStream_Release(&stream->ITextStream_iface);
return create_error(GetLastError());
}
}
*ret = &stream->ITextStream_iface; *ret = &stream->ITextStream_iface;
return S_OK; return S_OK;
} }

View File

@ -27,6 +27,7 @@ cpp_quote("#undef CopyFile")
cpp_quote("#undef DeleteFile") cpp_quote("#undef DeleteFile")
cpp_quote("#undef MoveFile") cpp_quote("#undef MoveFile")
cpp_quote("#endif") cpp_quote("#endif")
cpp_quote("#define CTL_E_ENDOFFILE STD_CTL_SCODE(62)") /* this is not defined in public headers */
[ [
uuid(420B2830-E718-11CF-893D-00A0C9054228), uuid(420B2830-E718-11CF-893D-00A0C9054228),

View File

@ -40,6 +40,8 @@ static inline ULONG get_refcount(IUnknown *iface)
return IUnknown_Release(iface); return IUnknown_Release(iface);
} }
static const WCHAR crlfW[] = {'\r','\n',0};
#define GET_REFCOUNT(iface) \ #define GET_REFCOUNT(iface) \
get_refcount((IUnknown*)iface) get_refcount((IUnknown*)iface)
@ -1293,6 +1295,7 @@ static void test_CreateTextFile(void)
{ {
static const WCHAR scrrunW[] = {'s','c','r','r','u','n','\\',0}; static const WCHAR scrrunW[] = {'s','c','r','r','u','n','\\',0};
static const WCHAR testfileW[] = {'t','e','s','t','.','t','x','t',0}; static const WCHAR testfileW[] = {'t','e','s','t','.','t','x','t',0};
static const WCHAR bomAW[] = {0xff,0xfe,0};
WCHAR pathW[MAX_PATH], dirW[MAX_PATH]; WCHAR pathW[MAX_PATH], dirW[MAX_PATH];
ITextStream *stream; ITextStream *stream;
BSTR nameW, str; BSTR nameW, str;
@ -1335,6 +1338,19 @@ static void test_CreateTextFile(void)
ok(hr == S_OK, "got 0x%08x\n", hr); ok(hr == S_OK, "got 0x%08x\n", hr);
ITextStream_Release(stream); ITextStream_Release(stream);
/* overwrite in Unicode mode, check for BOM */
hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_TRUE, &stream);
ok(hr == S_OK, "got 0x%08x\n", hr);
ITextStream_Release(stream);
hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateFalse, &stream);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = ITextStream_ReadAll(stream, &str);
ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
ok(!lstrcmpW(str, bomAW), "got %s\n", wine_dbgstr_w(str));
SysFreeString(str);
ITextStream_Release(stream);
DeleteFileW(nameW); DeleteFileW(nameW);
RemoveDirectoryW(dirW); RemoveDirectoryW(dirW);
SysFreeString(nameW); SysFreeString(nameW);
@ -1344,7 +1360,6 @@ static void test_WriteLine(void)
{ {
static const WCHAR scrrunW[] = {'s','c','r','r','u','n','\\',0}; static const WCHAR scrrunW[] = {'s','c','r','r','u','n','\\',0};
static const WCHAR testfileW[] = {'t','e','s','t','.','t','x','t',0}; static const WCHAR testfileW[] = {'t','e','s','t','.','t','x','t',0};
static const WCHAR crlfW[] = {'\r','\n',0};
WCHAR pathW[MAX_PATH], dirW[MAX_PATH]; WCHAR pathW[MAX_PATH], dirW[MAX_PATH];
WCHAR buffW[MAX_PATH], buff2W[MAX_PATH]; WCHAR buffW[MAX_PATH], buff2W[MAX_PATH];
char buffA[MAX_PATH]; char buffA[MAX_PATH];
@ -1415,6 +1430,137 @@ static void test_WriteLine(void)
SysFreeString(nameW); SysFreeString(nameW);
} }
static void test_ReadAll(void)
{
static const WCHAR scrrunW[] = {'s','c','r','r','u','n','\\',0};
static const WCHAR testfileW[] = {'t','e','s','t','.','t','x','t',0};
static const WCHAR secondlineW[] = {'s','e','c','o','n','d',0};
static const WCHAR aW[] = {'A',0};
WCHAR pathW[MAX_PATH], dirW[MAX_PATH], buffW[500];
ITextStream *stream;
BSTR nameW;
HRESULT hr;
BOOL ret;
BSTR str;
GetTempPathW(sizeof(pathW)/sizeof(WCHAR), pathW);
lstrcatW(pathW, scrrunW);
lstrcpyW(dirW, pathW);
lstrcatW(pathW, testfileW);
ret = CreateDirectoryW(dirW, NULL);
ok(ret, "got %d, %d\n", ret, GetLastError());
/* Unicode file -> read with ascii stream */
nameW = SysAllocString(pathW);
hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_TRUE, &stream);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = ITextStream_WriteLine(stream, nameW);
ok(hr == S_OK, "got 0x%08x\n", hr);
str = SysAllocString(secondlineW);
hr = ITextStream_WriteLine(stream, str);
ok(hr == S_OK, "got 0x%08x\n", hr);
SysFreeString(str);
hr = ITextStream_ReadAll(stream, NULL);
ok(hr == E_POINTER, "got 0x%08x\n", hr);
str = (void*)0xdeadbeef;
hr = ITextStream_ReadAll(stream, &str);
ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str);
ITextStream_Release(stream);
hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateFalse, &stream);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = ITextStream_ReadAll(stream, NULL);
ok(hr == E_POINTER, "got 0x%08x\n", hr);
/* Buffer content is not interpreted - BOM is kept, all data is converted to WCHARs */
str = NULL;
hr = ITextStream_ReadAll(stream, &str);
ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
ok(str[0] == 0x00ff && str[1] == 0x00fe, "got %s, %d\n", wine_dbgstr_w(str), SysStringLen(str));
SysFreeString(str);
ITextStream_Release(stream);
/* Unicode file -> read with unicode stream */
hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
ok(hr == S_OK, "got 0x%08x\n", hr);
lstrcpyW(buffW, nameW);
lstrcatW(buffW, crlfW);
lstrcatW(buffW, secondlineW);
lstrcatW(buffW, crlfW);
str = NULL;
hr = ITextStream_ReadAll(stream, &str);
ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str));
SysFreeString(str);
/* ReadAll one more time */
str = (void*)0xdeadbeef;
hr = ITextStream_ReadAll(stream, &str);
ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str);
/* ReadLine fails the same way */
str = (void*)0xdeadbeef;
hr = ITextStream_ReadLine(stream, &str);
ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str);
ITextStream_Release(stream);
/* Open again and skip first line before ReadAll */
hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
ok(hr == S_OK, "got 0x%08x\n", hr);
str = NULL;
hr = ITextStream_ReadLine(stream, &str);
todo_wine {
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(str != NULL, "got %p\n", str);
}
SysFreeString(str);
lstrcpyW(buffW, secondlineW);
lstrcatW(buffW, crlfW);
str = NULL;
hr = ITextStream_ReadAll(stream, &str);
ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
todo_wine
ok(!lstrcmpW(buffW, str), "got %s\n", wine_dbgstr_w(str));
SysFreeString(str);
ITextStream_Release(stream);
/* ASCII file, read with Unicode stream */
/* 1. one byte content, not enough for Unicode read */
hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_TRUE, VARIANT_FALSE, &stream);
ok(hr == S_OK, "got 0x%08x\n", hr);
str = SysAllocString(aW);
hr = ITextStream_Write(stream, str);
SysFreeString(str);
ITextStream_Release(stream);
hr = IFileSystem3_OpenTextFile(fs3, nameW, ForReading, VARIANT_FALSE, TristateTrue, &stream);
ok(hr == S_OK, "got 0x%08x\n", hr);
str = (void*)0xdeadbeef;
hr = ITextStream_ReadAll(stream, &str);
ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
ok(str == NULL || broken(str == (void*)0xdeadbeef) /* win2k */, "got %p\n", str);
ITextStream_Release(stream);
DeleteFileW(nameW);
RemoveDirectoryW(dirW);
SysFreeString(nameW);
}
START_TEST(filesystem) START_TEST(filesystem)
{ {
HRESULT hr; HRESULT hr;
@ -1445,6 +1591,7 @@ START_TEST(filesystem)
test_DriveCollection(); test_DriveCollection();
test_CreateTextFile(); test_CreateTextFile();
test_WriteLine(); test_WriteLine();
test_ReadAll();
IFileSystem3_Release(fs3); IFileSystem3_Release(fs3);

View File

@ -24,6 +24,7 @@ cpp_quote("#undef CopyFile")
cpp_quote("#undef DeleteFile") cpp_quote("#undef DeleteFile")
cpp_quote("#undef MoveFile") cpp_quote("#undef MoveFile")
cpp_quote("#endif") cpp_quote("#endif")
cpp_quote("#define CTL_E_ENDOFFILE STD_CTL_SCODE(62)") /* this is not defined in public headers */
[ [
uuid(420B2830-E718-11CF-893D-00A0C9054228), uuid(420B2830-E718-11CF-893D-00A0C9054228),