scrrun: Implement Read().
This commit is contained in:
parent
c927336c5a
commit
cc8ceb5177
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue