//----------------------------------------------------------------------- // This file is part of the Windows SDK Code Samples. // // Copyright (C) Microsoft Corporation. All rights reserved. // // This source code is intended only as a supplement to Microsoft // Development Tools and/or on-line documentation. See these other // materials for detailed information regarding Microsoft code samples. // // THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A // PARTICULAR PURPOSE. //----------------------------------------------------------------------- #include #include #include #pragma warning(disable : 4127) // conditional expression is constant #define CHKHR(stmt) do { hr = (stmt); if (FAILED(hr)) goto CleanUp; } while(0) #define HR(stmt) do { hr = (stmt); goto CleanUp; } while(0) #define SAFE_RELEASE(I) do { if (I){ I->Release(); } I = NULL; } while(0) //implement filestream that derives from IStream class FileStream : public IStream { FileStream(HANDLE hFile) { _refcount = 1; _hFile = hFile; } ~FileStream() { if (_hFile != INVALID_HANDLE_VALUE) { ::CloseHandle(_hFile); } } public: HRESULT static OpenFile(LPCWSTR pName, IStream ** ppStream, bool fWrite) { HANDLE hFile = ::CreateFileW(pName, fWrite ? GENERIC_WRITE : GENERIC_READ, FILE_SHARE_READ, NULL, fWrite ? CREATE_ALWAYS : OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) return HRESULT_FROM_WIN32(GetLastError()); *ppStream = new FileStream(hFile); if(*ppStream == NULL) CloseHandle(hFile); return S_OK; } virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, __RPC__deref_out _Result_nullonfailure_ void __RPC_FAR *__RPC_FAR *ppvObject) { if (!ppvObject) return E_INVALIDARG; (*ppvObject) = nullptr; if (iid == __uuidof(IUnknown) || iid == __uuidof(IStream) || iid == __uuidof(ISequentialStream)) { *ppvObject = static_cast(this); AddRef(); return S_OK; } else return E_NOINTERFACE; } virtual ULONG STDMETHODCALLTYPE AddRef(void) { return (ULONG)InterlockedIncrement(&_refcount); } virtual ULONG STDMETHODCALLTYPE Release(void) { ULONG res = (ULONG) InterlockedDecrement(&_refcount); if (res == 0) delete this; return res; } // ISequentialStream Interface public: virtual HRESULT STDMETHODCALLTYPE Read(_Out_writes_bytes_to_(cb, *pcbRead) void* pv, _In_ ULONG cb, _Out_opt_ ULONG* pcbRead) { BOOL rc = ReadFile(_hFile, pv, cb, pcbRead, NULL); return (rc) ? S_OK : HRESULT_FROM_WIN32(GetLastError()); } virtual HRESULT STDMETHODCALLTYPE Write(_In_reads_bytes_(cb) const void* pv, _In_ ULONG cb, _Out_opt_ ULONG* pcbWritten) { BOOL rc = WriteFile(_hFile, pv, cb, pcbWritten, NULL); return rc ? S_OK : HRESULT_FROM_WIN32(GetLastError()); } // IStream Interface public: virtual HRESULT STDMETHODCALLTYPE SetSize(ULARGE_INTEGER) { return E_NOTIMPL; } virtual HRESULT STDMETHODCALLTYPE CopyTo(_In_ IStream*, ULARGE_INTEGER, _Out_opt_ ULARGE_INTEGER*, _Out_opt_ ULARGE_INTEGER*) { return E_NOTIMPL; } virtual HRESULT STDMETHODCALLTYPE Commit(DWORD) { return E_NOTIMPL; } virtual HRESULT STDMETHODCALLTYPE Revert(void) { return E_NOTIMPL; } virtual HRESULT STDMETHODCALLTYPE LockRegion(ULARGE_INTEGER, ULARGE_INTEGER, DWORD) { return E_NOTIMPL; } virtual HRESULT STDMETHODCALLTYPE UnlockRegion(ULARGE_INTEGER, ULARGE_INTEGER, DWORD) { return E_NOTIMPL; } virtual HRESULT STDMETHODCALLTYPE Clone(__RPC__deref_out_opt IStream **) { return E_NOTIMPL; } virtual HRESULT STDMETHODCALLTYPE Seek(LARGE_INTEGER liDistanceToMove, DWORD dwOrigin, _Out_opt_ ULARGE_INTEGER* lpNewFilePointer) { DWORD dwMoveMethod; switch(dwOrigin) { case STREAM_SEEK_SET: dwMoveMethod = FILE_BEGIN; break; case STREAM_SEEK_CUR: dwMoveMethod = FILE_CURRENT; break; case STREAM_SEEK_END: dwMoveMethod = FILE_END; break; default: return STG_E_INVALIDFUNCTION; break; } if (SetFilePointerEx(_hFile, liDistanceToMove, (PLARGE_INTEGER) lpNewFilePointer, dwMoveMethod) == 0) return HRESULT_FROM_WIN32(GetLastError()); return S_OK; } virtual HRESULT STDMETHODCALLTYPE Stat(__RPC__out STATSTG* pStatstg, DWORD ) { if (GetFileSizeEx(_hFile, (PLARGE_INTEGER) &pStatstg->cbSize) == 0) return HRESULT_FROM_WIN32(GetLastError()); return S_OK; } private: HANDLE _hFile; LONG _refcount; }; void dotWhiteSpace(_In_reads_(len) WCHAR* buff, UINT len) { UINT cnt; for (cnt = 0; cnt < len; ++cnt) if (buff[cnt] == L'\n') buff[cnt] = L'.'; } HRESULT WriteAttributes(IXmlReader* pReader) { const WCHAR* pwszPrefix; const WCHAR* pwszLocalName; HRESULT hr = pReader->MoveToFirstAttribute(); if (S_FALSE == hr) return hr; if (S_OK != hr) { wprintf(L"\nXmlLite Error: %08.8lx\n", hr); return hr; } if (S_OK == hr) { for (;;) { if (!pReader->IsDefault()) { const UINT buffSize = 24; WCHAR buff[buffSize]; UINT charsRead = 0; if (FAILED(hr = pReader->GetPrefix(&pwszPrefix, NULL))) { wprintf(L"Error, Method: GetPrefix, error is %08.8lx", hr); return hr; } if (FAILED(hr = pReader->GetLocalName(&pwszLocalName, NULL))) { wprintf(L"Error, Method: GetLocalName, error is %08.8lx", hr); return hr; } for (;;) { hr = pReader->ReadValueChunk(buff, buffSize - 1, &charsRead); if (S_FALSE == hr || 0 == charsRead) break; if (S_OK != hr) { wprintf(L"\nXmlLite Error: %08.8lx\n", hr); return hr; } buff[charsRead] = L'\0'; dotWhiteSpace(buff, charsRead); wprintf(L"attribute chunk size:%d >%s<\n", charsRead, buff); } } if (S_OK != pReader->MoveToNextAttribute()) break; } } return hr; } int __cdecl wmain(int argc, _In_reads_(argc) WCHAR* argv[]) { HRESULT hr = S_OK; IStream *pFileStream = NULL; IXmlReader *pReader = NULL; XmlNodeType nodetype; if (argc != 2) { wprintf(L"Usage: XmlLiteChunkReader.exe name-of-input-file\n"); return 0; } //Open read-only input stream if (FAILED(hr = FileStream::OpenFile(argv[1], &pFileStream, FALSE))) { wprintf(L"Error creating file reader, error is %08.8lx", hr); HR(hr); } if (FAILED(hr = CreateXmlReader(__uuidof(IXmlReader), (void**) &pReader, NULL))) { wprintf(L"Error creating xml reader, error is %08.8lx", hr); HR(hr); } if (FAILED(hr = pReader->SetInput(pFileStream))) { wprintf(L"Error setting input for reader, error is %08.8lx", hr); HR(hr); } for (;;) { hr = pReader->Read(&nodetype); if (S_FALSE == hr) break; if (S_OK != hr) { wprintf(L"\nXmlLite Error: %08.8lx\n", hr); HR(hr); } switch (nodetype) { case XmlNodeType_Element: if (FAILED(hr = WriteAttributes(pReader))) { wprintf(L"Error, Method: WriteAttributes, error is %08.8lx", hr); HR(hr); } break; case XmlNodeType_Text: case XmlNodeType_Whitespace: const UINT buffSize = 24; WCHAR buff[buffSize]; UINT charsRead = 0; for (;;) { hr = pReader->ReadValueChunk(buff, buffSize - 1, &charsRead); if (S_FALSE == hr || 0 == charsRead) break; if (S_OK != hr) { wprintf(L"\nXmlLite Error: %08.8lx\n", hr); HR(hr); } buff[charsRead] = L'\0'; dotWhiteSpace(buff, charsRead); wprintf(L"element chunk size:%d >%s<\n", charsRead, buff); } break; } } wprintf(L"\n"); CleanUp: SAFE_RELEASE(pFileStream); SAFE_RELEASE(pReader); return hr; }