Nikolay Sivov : scrrun: Implement WriteLine/Write for ITextStream.
Alexandre Julliard
julliard at winehq.org
Tue Mar 18 14:15:05 CDT 2014
Module: wine
Branch: master
Commit: abcffadbf1082f3aadf22264b0eea395f8436303
URL: http://source.winehq.org/git/wine.git/?a=commit;h=abcffadbf1082f3aadf22264b0eea395f8436303
Author: Nikolay Sivov <nsivov at codeweavers.com>
Date: Tue Mar 18 10:58:08 2014 +0400
scrrun: Implement WriteLine/Write for ITextStream.
---
dlls/scrrun/filesystem.c | 95 ++++++++++++++++++++++++++++++++++++----
dlls/scrrun/scrrun.idl | 8 ++--
dlls/scrrun/tests/filesystem.c | 83 +++++++++++++++++++++++++++++++++++
3 files changed, 174 insertions(+), 12 deletions(-)
diff --git a/dlls/scrrun/filesystem.c b/dlls/scrrun/filesystem.c
index 1d47d73..f1fea06 100644
--- a/dlls/scrrun/filesystem.c
+++ b/dlls/scrrun/filesystem.c
@@ -109,6 +109,8 @@ struct textstream {
LONG ref;
IOMode mode;
+ BOOL unicode;
+ BOOL first_write;
HANDLE file;
};
@@ -209,7 +211,7 @@ static BOOL textstream_check_iomode(struct textstream *This, enum iotype type)
if (type == IORead)
return This->mode == ForWriting || This->mode == ForAppending;
else
- return TRUE;
+ return This->mode == ForReading;
}
static HRESULT WINAPI textstream_QueryInterface(ITextStream *iface, REFIID riid, void **obj)
@@ -374,18 +376,87 @@ static HRESULT WINAPI textstream_ReadAll(ITextStream *iface, BSTR *text)
return E_NOTIMPL;
}
+static HRESULT textstream_writestr(struct textstream *stream, BSTR text)
+{
+ DWORD written = 0;
+ 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 {
+ DWORD len = WideCharToMultiByte(CP_ACP, 0, text, SysStringLen(text), NULL, 0, NULL, NULL);
+ char *buffA;
+ HRESULT hr;
+
+ buffA = heap_alloc(len);
+ if (!buffA)
+ return E_OUTOFMEMORY;
+
+ WideCharToMultiByte(CP_ACP, 0, text, SysStringLen(text), buffA, len, NULL, NULL);
+ ret = WriteFile(stream->file, buffA, len, &written, NULL);
+ hr = (ret && written == len) ? S_OK : create_error(GetLastError());
+ heap_free(buffA);
+ return hr;
+ }
+}
+
static HRESULT WINAPI textstream_Write(ITextStream *iface, BSTR text)
{
struct textstream *This = impl_from_ITextStream(iface);
- FIXME("(%p)->(%s): stub\n", This, debugstr_w(text));
- return E_NOTIMPL;
+
+ TRACE("(%p)->(%s)\n", This, debugstr_w(text));
+
+ if (textstream_check_iomode(This, IOWrite))
+ return CTL_E_BADFILEMODE;
+
+ return textstream_writestr(This, text);
+}
+
+static HRESULT textstream_writecrlf(struct textstream *stream)
+{
+ static const WCHAR crlfW[] = {'\r','\n'};
+ static const char crlfA[] = {'\r','\n'};
+ DWORD written = 0, len;
+ const void *ptr;
+ BOOL ret;
+
+ if (stream->unicode) {
+ ptr = crlfW;
+ len = sizeof(crlfW);
+ }
+ else {
+ ptr = crlfA;
+ len = sizeof(crlfA);
+ }
+
+ ret = WriteFile(stream->file, ptr, len, &written, NULL);
+ return (ret && written == len) ? S_OK : create_error(GetLastError());
}
static HRESULT WINAPI textstream_WriteLine(ITextStream *iface, BSTR text)
{
struct textstream *This = impl_from_ITextStream(iface);
- FIXME("(%p)->(%s): stub\n", This, debugstr_w(text));
- return E_NOTIMPL;
+ HRESULT hr;
+
+ TRACE("(%p)->(%s)\n", This, debugstr_w(text));
+
+ if (textstream_check_iomode(This, IOWrite))
+ return CTL_E_BADFILEMODE;
+
+ hr = textstream_writestr(This, text);
+ if (SUCCEEDED(hr))
+ hr = textstream_writecrlf(This);
+ return hr;
}
static HRESULT WINAPI textstream_WriteBlankLines(ITextStream *iface, LONG lines)
@@ -439,7 +510,7 @@ static const ITextStreamVtbl textstreamvtbl = {
textstream_Close
};
-static HRESULT create_textstream(const WCHAR *filename, DWORD disposition, IOMode mode, ITextStream **ret)
+static HRESULT create_textstream(const WCHAR *filename, DWORD disposition, IOMode mode, BOOL unicode, ITextStream **ret)
{
struct textstream *stream;
DWORD access = 0;
@@ -466,6 +537,8 @@ static HRESULT create_textstream(const WCHAR *filename, DWORD disposition, IOMod
stream->ITextStream_iface.lpVtbl = &textstreamvtbl;
stream->ref = 1;
stream->mode = mode;
+ stream->unicode = unicode;
+ stream->first_write = TRUE;
stream->file = CreateFileW(filename, access, 0, NULL, disposition, FILE_ATTRIBUTE_NORMAL, NULL);
if (stream->file == INVALID_HANDLE_VALUE)
@@ -3295,7 +3368,7 @@ static HRESULT WINAPI filesys_CreateTextFile(IFileSystem3 *iface, BSTR filename,
TRACE("%p %s %d %d %p\n", iface, debugstr_w(filename), overwrite, unicode, stream);
disposition = overwrite == VARIANT_TRUE ? CREATE_ALWAYS : CREATE_NEW;
- return create_textstream(filename, disposition, ForWriting, stream);
+ return create_textstream(filename, disposition, ForWriting, !!unicode, stream);
}
static HRESULT WINAPI filesys_OpenTextFile(IFileSystem3 *iface, BSTR filename,
@@ -3306,7 +3379,13 @@ static HRESULT WINAPI filesys_OpenTextFile(IFileSystem3 *iface, BSTR filename,
TRACE("(%p)->(%s %d %d %d %p)\n", iface, debugstr_w(filename), mode, create, format, stream);
disposition = create == VARIANT_TRUE ? OPEN_ALWAYS : OPEN_EXISTING;
- return create_textstream(filename, disposition, mode, stream);
+
+ if (format == TristateUseDefault) {
+ FIXME("default format not handled, defaulting to unicode\n");
+ format = TristateTrue;
+ }
+
+ return create_textstream(filename, disposition, mode, format == TristateTrue, stream);
}
static HRESULT WINAPI filesys_GetStandardStream(IFileSystem3 *iface,
diff --git a/dlls/scrrun/scrrun.idl b/dlls/scrrun/scrrun.idl
index 33f1fbb..9cb9daf 100644
--- a/dlls/scrrun/scrrun.idl
+++ b/dlls/scrrun/scrrun.idl
@@ -54,10 +54,10 @@ library Scripting
typedef enum Tristate
{
- TristateTrue = 0xffffffff,
- TristateFalse = 0,
- TristateUseDefault = 0xfffffffe,
- TristateMixed = 0xfffffffe
+ TristateTrue = -1,
+ TristateFalse = 0,
+ TristateUseDefault = -2,
+ TristateMixed = -2
} Tristate;
typedef enum FileAttribute
diff --git a/dlls/scrrun/tests/filesystem.c b/dlls/scrrun/tests/filesystem.c
index 3e8d4bb..4897652 100644
--- a/dlls/scrrun/tests/filesystem.c
+++ b/dlls/scrrun/tests/filesystem.c
@@ -192,6 +192,13 @@ static void test_textstream(void)
hr = IFileSystem3_OpenTextFile(fs3, name, ForReading, VARIANT_FALSE, TristateFalse, &stream);
ok(hr == S_OK, "got 0x%08x\n", hr);
+ /* try to write when open for reading */
+ hr = ITextStream_WriteLine(stream, name);
+ ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
+
+ hr = ITextStream_Write(stream, name);
+ ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
+
b = 10;
hr = ITextStream_get_AtEndOfStream(stream, &b);
todo_wine {
@@ -1265,6 +1272,81 @@ static void test_CreateTextFile(void)
SysFreeString(nameW);
}
+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];
+ ITextStream *stream;
+ DWORD r, len;
+ HANDLE file;
+ BSTR nameW;
+ HRESULT hr;
+ BOOL ret;
+
+ 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());
+
+ /* create as ASCII file first */
+ nameW = SysAllocString(pathW);
+ hr = IFileSystem3_CreateTextFile(fs3, nameW, VARIANT_FALSE, VARIANT_FALSE, &stream);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ hr = ITextStream_WriteLine(stream, nameW);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ITextStream_Release(stream);
+
+ /* check contents */
+ file = CreateFileW(pathW, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ ok(file != INVALID_HANDLE_VALUE, "got %p\n", file);
+ r = 0;
+ ret = ReadFile(file, buffA, sizeof(buffA), &r, NULL);
+ ok(ret && r, "read %d, got %d, %d\n", r, ret, GetLastError());
+
+ len = MultiByteToWideChar(CP_ACP, 0, buffA, r, buffW, sizeof(buffW)/sizeof(WCHAR));
+ buffW[len] = 0;
+ lstrcpyW(buff2W, nameW);
+ lstrcatW(buff2W, crlfW);
+ ok(!lstrcmpW(buff2W, buffW), "got %s, expected %s\n", wine_dbgstr_w(buffW), wine_dbgstr_w(buff2W));
+ CloseHandle(file);
+ DeleteFileW(nameW);
+
+ /* same for unicode file */
+ 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);
+ ITextStream_Release(stream);
+
+ /* check contents */
+ file = CreateFileW(pathW, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ ok(file != INVALID_HANDLE_VALUE, "got %p\n", file);
+ r = 0;
+ ret = ReadFile(file, buffW, sizeof(buffW), &r, NULL);
+ ok(ret && r, "read %d, got %d, %d\n", r, ret, GetLastError());
+ buffW[r/sizeof(WCHAR)] = 0;
+
+ buff2W[0] = 0xfeff;
+ buff2W[1] = 0;
+ lstrcatW(buff2W, nameW);
+ lstrcatW(buff2W, crlfW);
+ ok(!lstrcmpW(buff2W, buffW), "got %s, expected %s\n", wine_dbgstr_w(buffW), wine_dbgstr_w(buff2W));
+ CloseHandle(file);
+ DeleteFileW(nameW);
+
+ RemoveDirectoryW(dirW);
+ SysFreeString(nameW);
+}
+
START_TEST(filesystem)
{
HRESULT hr;
@@ -1294,6 +1376,7 @@ START_TEST(filesystem)
test_FileCollection();
test_DriveCollection();
test_CreateTextFile();
+ test_WriteLine();
IFileSystem3_Release(fs3);
More information about the wine-cvs
mailing list