source: nscp/include/file_logger.hpp @ d7e265d

0.4.00.4.10.4.2
Last change on this file since d7e265d was d66ccee, checked in by Michael Medin <michael@…>, 2 years ago

Tweaks to make building faster

  • Property mode set to 100644
File size: 4.2 KB
Line 
1#pragma once
2
3#include <direct.h>
4#include <stdlib.h>
5#include <stdio.h>
6#include <string>
7
8
9namespace simple_file {
10
11#ifndef CSIDL_COMMON_APPDATA
12#define CSIDL_COMMON_APPDATA 0x0023
13#define CSIDL_LOCAL_APPDATA  0x001c
14#endif
15        typedef BOOL (WINAPI *fnSHGetSpecialFolderPath)(HWND hwndOwner, LPTSTR lpszPath, int nFolder, BOOL fCreate);
16                static BOOL WINAPI _SHGetSpecialFolderPath(HWND hwndOwner, LPTSTR lpszPath, int nFolder, BOOL fCreate) {
17                        static fnSHGetSpecialFolderPath __SHGetSpecialFolderPath = NULL;
18                        if (!__SHGetSpecialFolderPath) {
19                                HMODULE hDLL = LoadLibrary(_T("shell32.dll"));
20                                if (hDLL != NULL) {
21                                        __SHGetSpecialFolderPath = (fnSHGetSpecialFolderPath)GetProcAddress(hDLL,"SHGetSpecialFolderPathW");
22                                }
23                        }
24                        if(__SHGetSpecialFolderPath)
25                                return __SHGetSpecialFolderPath(hwndOwner, lpszPath, nFolder, fCreate);
26                        return FALSE;
27                }
28
29
30        class file_appender {
31                std::wstring file_;
32                std::wstring path_;
33                std::wstring filename_;
34        public:
35                file_appender(std::wstring path, std::wstring filename) : path_(path), filename_(filename) {}
36                file_appender() {}
37
38                void set_file(std::wstring path, std::wstring filename) {
39                        path_ = path;
40                        filename_ = filename;
41                }
42
43                inline std::wstring getFileName() {
44                        if (file_.empty())
45                                return getFileName(path_, filename_);
46                        return file_;
47                }
48                std::wstring getFileName(std::wstring pathname, std::wstring filename) {
49                        if (file_.empty()) {
50                                std::wstring path = getFolder() + _T("\\") + pathname;
51                                if (!directoryExists(path)) {
52                                        if (_wmkdir(path.c_str()) != 0)
53                                                return _T("");
54                                }
55                                file_ = path + _T("\\") + filename;
56                        }
57                        return file_;
58                }
59        private:
60                inline std::wstring getFolder() {
61                        TCHAR buf[MAX_PATH+1];
62                        if (!_SHGetSpecialFolderPath(NULL, buf, CSIDL_LOCAL_APPDATA, FALSE)) {
63                                return _T("") + error::lookup::last_error();
64                        }
65                        return buf;
66                }
67                bool directoryExists(std::wstring path) {
68                        DWORD dwAtt = ::GetFileAttributes(path.c_str());
69                        if (dwAtt == INVALID_FILE_ATTRIBUTES) {
70                                return false;
71                        } else if ((dwAtt&FILE_ATTRIBUTE_DIRECTORY)==FILE_ATTRIBUTE_DIRECTORY) {
72                                return true;
73                        }
74                        return false;
75                }
76
77                HANDLE openAppendOrNew(std::wstring file) {
78                        DWORD numberOfBytesWritten = 0;
79                        HANDLE hFile = ::CreateFile(file.c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
80                        if (hFile == INVALID_HANDLE_VALUE) {
81                                hFile = ::CreateFile(file.c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
82                                if (hFile != INVALID_HANDLE_VALUE) {
83                                        WORD wBOM = 0xFEFF;
84                                        ::WriteFile(hFile, &wBOM, sizeof(WORD), &numberOfBytesWritten, NULL);
85                                } else {
86                                        int x = 5;
87                                }
88                        }
89                        return hFile;
90                }
91        public:
92
93                bool writeEntry(std::wstring line) {
94                        DWORD numberOfBytesWritten;
95                        HANDLE hFile = openAppendOrNew(getFileName());
96                        if (hFile == INVALID_HANDLE_VALUE) {
97                                return false;
98                        }
99                        if (::SetFilePointer(hFile, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER) {
100                                // Ingore this error!
101                        }
102                        ::WriteFile(hFile, line.c_str(), (static_cast<DWORD>(line.length()))*(sizeof(TCHAR)), &numberOfBytesWritten, NULL);
103                        ::CloseHandle(hFile);
104                        return true;
105                }
106        };
107}
108
109namespace logging {
110        class file_logger : public simple_file::file_appender {
111                std::wstring datemask_;
112        public:
113                file_logger(std::wstring path, std::wstring filename) : file_appender(path, filename), datemask_(_T("%Y-%m-%d %H:%M:%S")) {
114                        _tzset();
115                }
116                void log(const std::wstring category, const wchar_t* file, const int line, const wchar_t* message) {
117                        TCHAR buffer[65];
118                        __time64_t ltime;
119                        _time64( &ltime );
120                        struct tm *today = _localtime64( &ltime );
121                        if (today) {
122                                size_t len = wcsftime(buffer, 63, datemask_.c_str(), today);
123                                if ((len < 1)||(len > 64))
124                                        wcsncpy(buffer, 64, _T("???"));
125                                else
126                                        buffer[len] = 0;
127                        } else {
128                                wcsncpy(buffer, 64, _T("<unknown time>"));
129                        }
130                        std::wstring logline = std::wstring(buffer) + _T(": ") + category + _T(":") + std::wstring(file) + _T(":") + strEx::itos(line) +_T(": ") + message + _T("\r\n");
131                        if (!writeEntry(logline)) {
132                                std::wcerr << _T("Failed to write: ") << logline;
133                        }
134                }
135        };
136}
Note: See TracBrowser for help on using the repository browser.