Module: wine Branch: master Commit: abcffadbf1082f3aadf22264b0eea395f8436303 URL: http://source.winehq.org/git/wine.git/?a=commit;h=abcffadbf1082f3aadf22264b0...
Author: Nikolay Sivov nsivov@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);