17247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes/*
27247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes                            __  __            _
37247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes                         ___\ \/ /_ __   __ _| |_
47247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes                        / _ \\  /| '_ \ / _` | __|
57247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes                       |  __//  \| |_) | (_| | |_
67247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes                        \___/_/\_\ .__/ \__,_|\__|
77247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes                                 |_| XML parser
87247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes
97247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes   Copyright (c) 1997-2000 Thai Open Source Software Center Ltd
107247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes   Copyright (c) 2000-2017 Expat development team
117247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes   Licensed under the MIT license:
127247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes
137247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes   Permission is  hereby granted,  free of charge,  to any  person obtaining
147247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes   a  copy  of  this  software   and  associated  documentation  files  (the
157247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes   "Software"),  to  deal in  the  Software  without restriction,  including
167247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes   without  limitation the  rights  to use,  copy,  modify, merge,  publish,
177247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes   distribute, sublicense, and/or sell copies of the Software, and to permit
187247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes   persons  to whom  the Software  is  furnished to  do so,  subject to  the
197247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes   following conditions:
207247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes
217247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes   The above copyright  notice and this permission notice  shall be included
227247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes   in all copies or substantial portions of the Software.
237247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes
247247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes   THE  SOFTWARE  IS  PROVIDED  "AS  IS",  WITHOUT  WARRANTY  OF  ANY  KIND,
257247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes   EXPRESS  OR IMPLIED,  INCLUDING  BUT  NOT LIMITED  TO  THE WARRANTIES  OF
267247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
277247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes   NO EVENT SHALL THE AUTHORS OR  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
287247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes   DAMAGES OR  OTHER LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT,  TORT OR
297247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes   OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
307247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes   USE OR OTHER DEALINGS IN THE SOFTWARE.
317247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes*/
327247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes
337247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes#define STRICT 1
347247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes#define WIN32_LEAN_AND_MEAN 1
357247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes
367247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes#ifdef XML_UNICODE_WCHAR_T
377247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes# ifndef XML_UNICODE
387247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes#  define XML_UNICODE
397247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes# endif
407247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes#endif
417247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes
427247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes#ifdef XML_UNICODE
437247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes# define UNICODE
447247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes# define _UNICODE
457247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes#endif /* XML_UNICODE */
467247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes#include <windows.h>
477247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes#include <stdio.h>
487247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes#include <tchar.h>
497247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes#include "filemap.h"
507247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes
517247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughesstatic void win32perror(const TCHAR *);
527247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes
537247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughesint
547247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughesfilemap(const TCHAR *name,
557247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes        void (*processor)(const void *, size_t, const TCHAR *, void *arg),
567247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes        void *arg)
577247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes{
587247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes  HANDLE f;
597247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes  HANDLE m;
607247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes  DWORD size;
617247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes  DWORD sizeHi;
627247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes  void *p;
637247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes
647247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes  f = CreateFile(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
657247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes                          FILE_FLAG_SEQUENTIAL_SCAN, NULL);
667247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes  if (f == INVALID_HANDLE_VALUE) {
677247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes    win32perror(name);
687247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes    return 0;
697247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes  }
707247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes  size = GetFileSize(f, &sizeHi);
717247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes  if (size == (DWORD)-1) {
727247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes    win32perror(name);
737247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes    CloseHandle(f);
747247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes    return 0;
757247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes  }
767247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes  if (sizeHi || (size > XML_MAX_CHUNK_LEN)) {
777247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes    CloseHandle(f);
787247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes    return 2;  /* Cannot be passed to XML_Parse in one go */
797247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes  }
807247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes  /* CreateFileMapping barfs on zero length files */
817247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes  if (size == 0) {
827247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes    static const char c = '\0';
837247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes    processor(&c, 0, name, arg);
847247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes    CloseHandle(f);
857247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes    return 1;
867247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes  }
877247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes  m = CreateFileMapping(f, NULL, PAGE_READONLY, 0, 0, NULL);
887247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes  if (m == NULL) {
897247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes    win32perror(name);
907247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes    CloseHandle(f);
917247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes    return 0;
927247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes  }
937247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes  p = MapViewOfFile(m, FILE_MAP_READ, 0, 0, 0);
947247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes  if (p == NULL) {
957247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes    win32perror(name);
967247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes    CloseHandle(m);
977247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes    CloseHandle(f);
987247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes    return 0;
997247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes  }
1007247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes  processor(p, size, name, arg);
1017247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes  UnmapViewOfFile(p);
1027247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes  CloseHandle(m);
1037247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes  CloseHandle(f);
1047247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes  return 1;
1057247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes}
1067247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes
1077247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughesstatic void
1087247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hugheswin32perror(const TCHAR *s)
1097247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes{
1107247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes  LPVOID buf;
1117247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes  if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
1127247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes                    | FORMAT_MESSAGE_FROM_SYSTEM,
1137247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes                    NULL,
1147247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes                    GetLastError(),
1157247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes                    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
1167247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes                    (LPTSTR) &buf,
1177247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes                    0,
1187247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes                    NULL)) {
1197247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes    _ftprintf(stderr, _T("%s: %s"), s, buf);
1207247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes    fflush(stderr);
1217247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes    LocalFree(buf);
1227247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes  }
1237247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes  else
1247247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes    _ftprintf(stderr, _T("%s: unknown Windows error\n"), s);
1257247294fbc43cb0b4fb2ea03d952b81077db7c27Elliott Hughes}
126