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