scrrun: Implement ReadAll().
This commit is contained in:
parent
ec3417e290
commit
c927336c5a
|
@ -37,6 +37,7 @@
|
|||
WINE_DEFAULT_DEBUG_CHANNEL(scrrun);
|
||||
|
||||
static const WCHAR bsW[] = {'\\',0};
|
||||
static const WCHAR utf16bom = 0xfeff;
|
||||
|
||||
struct foldercollection {
|
||||
IFolderCollection IFolderCollection_iface;
|
||||
|
@ -110,7 +111,7 @@ struct textstream {
|
|||
|
||||
IOMode mode;
|
||||
BOOL unicode;
|
||||
BOOL first_write;
|
||||
BOOL first_read;
|
||||
LARGE_INTEGER size;
|
||||
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)
|
||||
{
|
||||
struct textstream *This = impl_from_ITextStream(iface);
|
||||
VARIANT_BOOL eos;
|
||||
HRESULT hr;
|
||||
|
||||
FIXME("(%p)->(%p): stub\n", This, text);
|
||||
|
||||
if (!text)
|
||||
return E_POINTER;
|
||||
|
||||
*text = NULL;
|
||||
if (textstream_check_iomode(This, IORead))
|
||||
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;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI textstream_ReadAll(ITextStream *iface, BSTR *text)
|
||||
{
|
||||
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))
|
||||
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)
|
||||
|
@ -399,15 +491,6 @@ static HRESULT textstream_writestr(struct textstream *stream, BSTR text)
|
|||
BOOL ret;
|
||||
|
||||
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);
|
||||
return (ret && written == SysStringByteLen(text)) ? S_OK : create_error(GetLastError());
|
||||
} else {
|
||||
|
@ -555,7 +638,7 @@ static HRESULT create_textstream(const WCHAR *filename, DWORD disposition, IOMod
|
|||
stream->ref = 1;
|
||||
stream->mode = mode;
|
||||
stream->unicode = unicode;
|
||||
stream->first_write = TRUE;
|
||||
stream->first_read = TRUE;
|
||||
|
||||
stream->file = CreateFileW(filename, access, 0, NULL, disposition, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (stream->file == INVALID_HANDLE_VALUE)
|
||||
|
@ -570,6 +653,16 @@ static HRESULT create_textstream(const WCHAR *filename, DWORD disposition, IOMod
|
|||
else
|
||||
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;
|
||||
return S_OK;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ cpp_quote("#undef CopyFile")
|
|||
cpp_quote("#undef DeleteFile")
|
||||
cpp_quote("#undef MoveFile")
|
||||
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),
|
||||
|
|
|
@ -40,6 +40,8 @@ static inline ULONG get_refcount(IUnknown *iface)
|
|||
return IUnknown_Release(iface);
|
||||
}
|
||||
|
||||
static const WCHAR crlfW[] = {'\r','\n',0};
|
||||
|
||||
#define GET_REFCOUNT(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 testfileW[] = {'t','e','s','t','.','t','x','t',0};
|
||||
static const WCHAR bomAW[] = {0xff,0xfe,0};
|
||||
WCHAR pathW[MAX_PATH], dirW[MAX_PATH];
|
||||
ITextStream *stream;
|
||||
BSTR nameW, str;
|
||||
|
@ -1335,6 +1338,19 @@ static void test_CreateTextFile(void)
|
|||
ok(hr == S_OK, "got 0x%08x\n", hr);
|
||||
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);
|
||||
RemoveDirectoryW(dirW);
|
||||
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 testfileW[] = {'t','e','s','t','.','t','x','t',0};
|
||||
static const WCHAR crlfW[] = {'\r','\n',0};
|
||||
WCHAR pathW[MAX_PATH], dirW[MAX_PATH];
|
||||
WCHAR buffW[MAX_PATH], buff2W[MAX_PATH];
|
||||
char buffA[MAX_PATH];
|
||||
|
@ -1415,6 +1430,137 @@ static void test_WriteLine(void)
|
|||
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)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
@ -1445,6 +1591,7 @@ START_TEST(filesystem)
|
|||
test_DriveCollection();
|
||||
test_CreateTextFile();
|
||||
test_WriteLine();
|
||||
test_ReadAll();
|
||||
|
||||
IFileSystem3_Release(fs3);
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ cpp_quote("#undef CopyFile")
|
|||
cpp_quote("#undef DeleteFile")
|
||||
cpp_quote("#undef MoveFile")
|
||||
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),
|
||||
|
|
Loading…
Reference in New Issue