scrrun: Implement Read().

This commit is contained in:
Nikolay Sivov 2014-04-03 17:34:52 +04:00 committed by Alexandre Julliard
parent c927336c5a
commit cc8ceb5177
2 changed files with 248 additions and 49 deletions

View File

@ -361,15 +361,109 @@ static HRESULT WINAPI textstream_get_AtEndOfLine(ITextStream *iface, VARIANT_BOO
return E_NOTIMPL;
}
/*
Reads 'toread' bytes from a file, converts if needed
BOM is skipped if 'bof' is set.
*/
static HRESULT textstream_read(struct textstream *stream, LONG toread, BOOL bof, BSTR *text)
{
HRESULT hr = S_OK;
DWORD read;
char *buff;
BOOL ret;
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(stream->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;
}
if (stream->unicode) {
int i = 0;
/* skip BOM */
if (bof && *(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 WINAPI textstream_Read(ITextStream *iface, LONG len, BSTR *text)
{
struct textstream *This = impl_from_ITextStream(iface);
FIXME("(%p)->(%p): stub\n", This, text);
LARGE_INTEGER start, end, dist;
DWORD toread;
HRESULT hr;
TRACE("(%p)->(%d %p)\n", This, len, text);
if (!text)
return E_POINTER;
*text = NULL;
if (len <= 0)
return len == 0 ? S_OK : E_INVALIDARG;
if (textstream_check_iomode(This, IORead))
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 (This->unicode) len *= sizeof(WCHAR);
hr = textstream_read(This, min(toread, len), start.QuadPart == 0, text);
if (FAILED(hr))
return hr;
else
return toread <= len ? S_FALSE : S_OK;
}
static HRESULT WINAPI textstream_ReadLine(ITextStream *iface, BSTR *text)
@ -402,10 +496,8 @@ static HRESULT WINAPI textstream_ReadAll(ITextStream *iface, BSTR *text)
{
struct textstream *This = impl_from_ITextStream(iface);
LARGE_INTEGER start, end, dist;
DWORD toread, read;
DWORD toread;
HRESULT hr;
char *buff;
BOOL ret;
TRACE("(%p)->(%p)\n", This, text);
@ -439,50 +531,8 @@ static HRESULT WINAPI textstream_ReadAll(ITextStream *iface, BSTR *text)
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;
hr = textstream_read(This, toread, start.QuadPart == 0, text);
return FAILED(hr) ? hr : S_FALSE;
}
static HRESULT textstream_writestr(struct textstream *stream, BSTR text)

View File

@ -1561,6 +1561,154 @@ todo_wine
SysFreeString(nameW);
}
static void test_Read(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_Read(stream, 0, NULL);
ok(hr == E_POINTER, "got 0x%08x\n", hr);
hr = ITextStream_Read(stream, 1, NULL);
ok(hr == E_POINTER, "got 0x%08x\n", hr);
hr = ITextStream_Read(stream, -1, NULL);
ok(hr == E_POINTER, "got 0x%08x\n", hr);
str = (void*)0xdeadbeef;
hr = ITextStream_Read(stream, 1, &str);
ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
ok(str == NULL, "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_Read(stream, 1, NULL);
ok(hr == E_POINTER, "got 0x%08x\n", hr);
str = (void*)0xdeadbeef;
hr = ITextStream_Read(stream, -1, &str);
ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
ok(str == NULL, "got %p\n", str);
str = (void*)0xdeadbeef;
hr = ITextStream_Read(stream, 0, &str);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(str == NULL, "got %p\n", str);
/* Buffer content is not interpreted - BOM is kept, all data is converted to WCHARs */
str = NULL;
hr = ITextStream_Read(stream, 2, &str);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(str[0] == 0x00ff && str[1] == 0x00fe, "got %s, %d\n", wine_dbgstr_w(str), SysStringLen(str));
ok(SysStringLen(str) == 2, "got %d\n", 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_Read(stream, 500, &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_Read(stream, 10, &str);
ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
ok(str == NULL, "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), "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_Read(stream, 100, &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_Read(stream, 500, &str);
ok(hr == CTL_E_ENDOFFILE, "got 0x%08x\n", hr);
ok(str == NULL, "got %p\n", str);
ITextStream_Release(stream);
DeleteFileW(nameW);
RemoveDirectoryW(dirW);
SysFreeString(nameW);
}
START_TEST(filesystem)
{
HRESULT hr;
@ -1592,6 +1740,7 @@ START_TEST(filesystem)
test_CreateTextFile();
test_WriteLine();
test_ReadAll();
test_Read();
IFileSystem3_Release(fs3);