root/lang/objective-cplusplus/i3/trunk/src/os-windows/Os.cpp @ 36013

Revision 35906, 14.8 kB (checked in by saturday06, 4 years ago)

jiojoijoijoi

Line 
1#include <PrecompiledHeaders.h>
2#include "Common.h"
3
4#include <malloc.h>
5#include <aclapi.h>
6#include <lmcons.h>
7
8using namespace mil;
9
10namespace i3 {
11
12static Os mutable_os;
13const Os& os = mutable_os;
14static TCHAR config_dir[STACKABLE_MAX_PATH] = {};
15static TCHAR program_dir[STACKABLE_MAX_PATH] = {};
16
17/*
18const TCHAR* get_config_dir() {
19    if (_tcsnlen(config_dir, _countof(config_dir)) == 0) {
20  init_config_dir();
21     if (_tcsnlen(config_dir, _countof(config_dir)) == 0) {
22         return NULL;
23  }
24    }
25    return config_dir;
26}
27*/
28
29
30namespace secure_config {
31
32BOOL CreateSecureDirectory(const TCHAR* lpszFileName, PSID pSidOwner, PACL pDacl) {
33    SECURITY_ATTRIBUTES  securityAttributes = {};
34    PSECURITY_DESCRIPTOR pSecurityDescriptor =
35        (PSECURITY_DESCRIPTOR)malloc(SECURITY_DESCRIPTOR_MIN_LENGTH);
36    if (!pSecurityDescriptor) {
37        return FALSE;
38    }
39
40    if (!InitializeSecurityDescriptor(pSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION)) {
41        return FALSE;
42    }
43
44    if (!SetSecurityDescriptorDacl(pSecurityDescriptor, TRUE, pDacl, FALSE)) {
45        return FALSE;
46    }
47
48    if (!SetSecurityDescriptorOwner(pSecurityDescriptor, pSidOwner, FALSE)) {
49        return FALSE;
50    }
51
52    securityAttributes.nLength              = sizeof(SECURITY_ATTRIBUTES);
53    securityAttributes.lpSecurityDescriptor = pSecurityDescriptor;
54    securityAttributes.bInheritHandle       = FALSE;
55
56    BOOL result = CreateDirectory(lpszFileName, &securityAttributes);
57    //DWORD e = GetLastError();
58    free(pSecurityDescriptor);
59
60    return result;
61}
62
63
64BOOL ConvertNameToSid(const TCHAR* lpszName, PSID *ppSid) {
65    TCHAR szDomainName[256] = {};
66    DWORD dwSizeDomain = _countof(szDomainName);
67    DWORD dwSizeSid = 0;
68    SID_NAME_USE sidName;
69
70    LookupAccountName(NULL, lpszName, NULL, &dwSizeSid, szDomainName, &dwSizeDomain, &sidName);
71    if (dwSizeSid <= 0) {
72        // what ?
73        return FALSE;
74    }
75    *ppSid = (PSID)malloc(dwSizeSid);
76    if (!*ppSid) {
77        return FALSE;
78    }
79
80    return LookupAccountName(NULL, lpszName, *ppSid, &dwSizeSid, szDomainName, &dwSizeDomain, &sidName);
81}
82
83}
84
85using namespace secure_config;
86
87
88void init_config_dir2() {
89    //XXX clean handles ???
90    TCHAR config_dir_temp[STACKABLE_MAX_PATH] = {};
91
92    if (!_tcscpy_s(config_dir_temp, program_dir)) {
93        return;
94    }
95
96    if (_tcscat_s(config_dir_temp, _T("\\settings")) != 0) {
97        return;
98    }
99
100        int exists = PathFileExists(config_dir_temp);
101    if (!PathIsDirectory(config_dir_temp)) {
102        return;
103    }
104
105    PSID pSid = NULL;
106    TCHAR szAccountName[UNLEN] = {};
107    DWORD dwAccountNameSize = _countof(szAccountName) - 1;
108
109    if (!GetUserName(szAccountName, &dwAccountNameSize)) {
110        return;
111    }
112    if (!ConvertNameToSid(szAccountName, &pSid)) {
113        return;
114    }
115
116    if (!exists) {
117        PACL pDacl = NULL;
118        EXPLICIT_ACCESS explicitAccess = {};
119
120        BuildExplicitAccessWithName(
121            &explicitAccess, _T("Everyone"),
122            GENERIC_READ | FILE_ADD_SUBDIRECTORY,
123            GRANT_ACCESS,
124            NO_INHERITANCE);
125        if (SetEntriesInAcl(1, &explicitAccess, NULL, &pDacl) != ERROR_SUCCESS) {
126            return;
127        }
128
129        if (!CreateSecureDirectory(config_dir_temp, pSid, pDacl)) {
130            return;
131        }
132
133        LocalFree(pDacl);
134    }
135
136    {
137        PACL  pDacl = NULL;
138        EXPLICIT_ACCESS explicitAccess = {};
139
140        if (_tcscat_s(config_dir_temp, _T("\\")) != 0) {
141            return;
142        }
143
144        if (_tcscat_s(config_dir_temp, szAccountName) != 0) {
145            return;
146        }
147
148        BOOL exists = PathFileExists(config_dir_temp);
149        if (exists && !PathIsDirectory(config_dir_temp)) {
150            return;
151        }
152
153        if (exists) {
154            _tcscpy_s(config_dir, config_dir_temp);
155            return;
156        }
157
158        BuildExplicitAccessWithName(&explicitAccess, szAccountName, GENERIC_ALL, GRANT_ACCESS, 0);
159        if (SetEntriesInAcl(1, &explicitAccess, NULL, &pDacl) != ERROR_SUCCESS) {
160            return;
161        }
162
163        if (!CreateSecureDirectory(config_dir_temp, pSid, pDacl)) {
164            return;
165        }
166
167        LocalFree(pDacl);
168    }
169    _tcscpy_s(config_dir, config_dir_temp);
170    return;
171}
172
173void init_config_dir() {
174
175#ifndef _WIN32_WCE
176    LPITEMIDLIST pidl = NULL;
177    IMalloc* pMalloc = NULL;
178
179    if (SHGetMalloc(&pMalloc) != S_OK) {
180        // error
181        return;
182    }
183
184    if (FAILED(SHGetSpecialFolderLocation(NULL, CSIDL_APPDATA, &pidl))) {
185        // error
186        pMalloc->Release();
187        return;
188    }
189
190    if (SHGetPathFromIDList(pidl, mutable_os.config_dir) != TRUE) {
191        // error
192        pMalloc->Free(pidl);
193        pMalloc->Release();
194        return;
195    }
196
197    pMalloc->Free(pidl);
198    pMalloc->Release();
199
200    if (_tcscat_s(config_dir, _countof(config_dir), _T("\\") _T(PACKAGE_NAME)) != 0) {
201        memset(config_dir, 0, sizeof(config_dir));
202        return;
203    }
204
205    //TODO:
206    //if (!PathFileExists(config_dir) && _tmkdir(config_dir)) {
207    //    // error
208    //    memset(config_dir, 0, sizeof(config_dir));
209    //    return;
210    //}// else if (!PathIsDirectory(config_dir)) {
211    //    return;
212    //}
213#endif
214}
215
216exit_status init_os_global_data(int argc, char** argv) {
217    //_fmode = _O_BINARY;
218    //_set_fmode(_O_BINARY);
219
220    if (!i3::hInstance) {
221        i3::hInstance = GetModuleHandle(NULL);
222    }
223
224    mutable_os.program_dir = program_dir;
225    mutable_os.config_dir = config_dir;
226    mutable_os.osversioninfo.dwOSVersionInfoSize = sizeof(mutable_os.osversioninfo);
227    if (!GetVersionEx(&mutable_os.osversioninfo)) {
228        return 0;
229    }
230
231    init_config_dir();
232
233#ifdef ENABLE_NLS
234#undef LOCALEDIR
235    using namespace std;
236
237    if (setlocale(LC_ALL, "") == NULL) {
238        return 0;
239    }
240
241    DWORD result = GetModuleFileName(
242                       GetModuleHandle(NULL),
243                       program_dir,
244                       _countof(program_dir) - 1);
245    if (result == 0 || result == _countof(program_dir) - 1) {
246        return 0;
247    }
248
249    if (PathRemoveFileSpec(program_dir) == FALSE) {
250        return 0;
251    }
252
253    TCHAR locale_dir[STACKABLE_MAX_PATH] = {};
254    if (_tcscpy_s(locale_dir, program_dir) != 0) {
255        return 0;
256    }
257    if (_tcscat_s(locale_dir, _T("\\locale")) != 0) {
258        return 0;
259    }
260
261#if defined(UNICODE) || defined(_UNICODE)
262#ifdef HAVE_WBINDTEXTDOMAIN
263    wbindtextdomain(PACKAGE_NAME, locale_dir);
264#else
265    {
266        int acp = GetACP();
267        int num_elements = WideCharToMultiByte(acp, 0, locale_dir, -1, NULL, 0, 0, 0);
268        if (num_elements == 0) {
269            return 0;
270        }
271
272        char* locale_dir8 = (char*)calloc(num_elements, 1);
273        if (!locale_dir8) {
274            return 0;
275        }
276
277        if (WideCharToMultiByte(acp, 0, locale_dir, -1, locale_dir8, num_elements, 0, 0)) {
278            bindtextdomain(PACKAGE_NAME, locale_dir8);
279        }
280        free (locale_dir8);
281    }
282#endif
283#else
284    bindtextdomain(PACKAGE_NAME, locale_dir);
285#endif
286    textdomain(PACKAGE_NAME);
287#endif
288
289
290//#ifdef HAVE_POPT_H
291//#if defined(UNICODE) || defined(_UNICODE)
292//    return check_args();
293//#else
294//    return execute_popt(argc, argv, boost::lambda::constant(stdout));
295//#endif
296//#endif
297
298    return 0;
299}
300extern HINSTANCE hInstance;
301}
302
303int APIENTRY _tWinMain(HINSTANCE hInstance,
304                       HINSTANCE hPrevInstance,
305                       LPTSTR    lpCmdLine,
306                       int       nCmdShow) {
307    UNREFERENCED_PARAMETER(hPrevInstance);
308    UNREFERENCED_PARAMETER(lpCmdLine);
309    UNREFERENCED_PARAMETER(nCmdShow);
310
311    i3::hInstance = hInstance;
312
313#ifdef __GNUC__
314    MessageBoxA(NULL, "GCC de WinMain !", "GCC de WinMain !", MB_OK);
315#endif
316
317    return main(0, 0);
318}
319
320// -----------------------------------------------------------------
321//
322// argument
323//
324// -----------------------------------------------------------------
325//#ifndef _MSC_VER
326#ifdef HAVE_POPT_H
327#include <boost/spirit/include/classic.hpp>
328#include <boost/bind.hpp>
329#include "Utf8ToUtf16Stream.h"
330
331using namespace boost::spirit::classic;
332
333namespace i3 {
334namespace windows_execute_popt {
335
336template <int Mode, typename Result>
337struct calc : public grammar<calc<Mode, Result> > {
338    Result& data;
339    calc(Result& data) : data(data) {}
340    void operator()(const char* first, const char* last) const;
341    template<typename S> struct definition {
342        rule<S> args, raw, quated;
343        definition(const calc<Mode, Result>& self) {
344            args   = (*space_p) >> (+(quated | raw))[self] >> (+space_p) >> args;
345            quated = ch_p('"') >> (*((ch_p('\\') >> (anychar_p | str_p("\r\n"))) | (anychar_p - ch_p('"')          ))) >> (ch_p('"') | end_p);
346            raw    =              (+((ch_p('\\') >> (anychar_p | str_p("\r\n"))) | (anychar_p - ch_p('"') - space_p)));
347        }
348        const rule<S>& start() const {
349            return args;
350        }
351    };
352};
353
354template <>
355void calc<0, size_t>::operator()(const char* first, const char* last) const {
356    data++;
357}
358
359template <>
360void calc<1, size_t*>::operator()(const char* first, const char* last) const {
361    *data = last - first + 1;
362    data++;
363}
364
365struct calc2 : public grammar<calc2> {
366    char*& data;
367    calc2(char*& data) : data(data) {}
368    void operator()(char c) const {
369        *data = c;
370        data++;
371    }
372    template<typename S> struct definition {
373        rule<S> args;
374        definition(const calc2& self) {
375            args   = (+((ch_p("\\") >> anychar_p[self]) | ch_p('"') | anychar_p[self]));
376        }
377        const rule<S>& start() const {
378            return args;
379        }
380    };
381};
382
383void calc2_helper(char* got, char* cleaned) {
384    calc2 c(cleaned);
385    parse_info<> r = boost::spirit::classic::parse(got, c);
386}
387
388template <>
389void calc<2, char**>::operator()(const char* first, const char* last) const {
390    size_t buf_size = last - first + 1;
391    char* got = NULL;
392    char* cleaned = NULL;
393
394    memset((void*)(*data), 0, buf_size);
395
396    if (buf_size > _ALLOCA_S_THRESHOLD) {
397        data++;
398        return;
399    }
400
401    __try {
402        got = (char*)alloca(buf_size);
403    } __except (GetExceptionCode() == STATUS_STACK_OVERFLOW ?
404                EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
405        data++;
406        return;
407    }
408
409    __try {
410        cleaned = (char*)alloca(buf_size);
411    } __except (GetExceptionCode() == STATUS_STACK_OVERFLOW ?
412                EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
413        data++;
414        return;
415    }
416
417    char* cleaned_begin = cleaned;
418    memset(got, 0, buf_size);
419    memset(cleaned, 0, buf_size);
420    memcpy(got, first, last - first);
421
422    calc2_helper(got, cleaned);
423
424    memcpy((void*)(*data), cleaned_begin, buf_size);
425    data++;
426}
427
428size_t get_argc(const char* line) {
429    size_t argc = 0; // must zero.
430    calc<0, size_t> c(argc);
431    parse_info<> r = parse(line, c);
432
433    return argc;
434}
435
436void get_size_list(const char* line,
437                   size_t* size_list,
438                   size_t argc) {
439
440    calc<1, size_t*> c(size_list);
441    parse_info<> r = parse(line, c);
442}
443
444void get_argv(const char* line,
445              const size_t* size_list,
446              char** argv, size_t argc) {
447
448    calc<2, char**> c(argv);
449    parse_info<> r = parse(line, c);
450}
451
452struct fp_func {
453    Utf8ToUtf16Stream& s;
454    FILE* operator()() {
455        return s.get();
456    }
457};
458
459exit_status check_args2(int argc, char** argv) {
460#if defined(UNICODE) || defined(_UNICODE)
461#ifdef ENABLE_NLS
462    Utf8ToUtf16Stream s(stderr);
463    struct fp_func fp_func = {s};
464    bind_textdomain_codeset(PACKAGE_NAME,"UTF-8");
465    exit_status e = i3::execute_popt((size_t)argc, (const char**)argv, fp_func);
466    bind_textdomain_codeset(PACKAGE_NAME,"UTF-16LE");
467#else
468    exit_status e = i3::execute_popt((size_t)argc, (const char**)argv, boost::lambda::constant(stdout));
469#endif
470#else
471#ifdef ENABLE_NLS
472    const char* codeset = bind_textdomain_codeset(PACKAGE_NAME,NULL);
473    bind_textdomain_codeset(PACKAGE_NAME,"UTF-8");
474    exit_status e = i3::execute_popt((size_t)argc, (const char**)argv, boost::lambda::constant(stdout));
475    bind_textdomain_codeset(PACKAGE_NAME,codeset);
476#else
477    exit_status e = i3::execute_popt((size_t)argc, (const char**)argv, boost::lambda::constant(stdout));
478#endif
479#endif
480    return e;
481}
482
483}
484
485
486#if defined(UNICODE) || defined(_UNICODE)
487exit_status check_args() {
488    using namespace i3::windows_execute_popt;
489
490    // --------------------------------------------
491    // phase 1
492    size_t argc = 0;
493    UTF16LE_TO_UTF8_ALLOCA(GetCommandLine(), line);
494    if (!line) {
495        return 1;
496    }
497    {
498        argc = get_argc(line);
499        if (argc == 0 || argc == 1) {
500            return 0;
501        }
502    }
503
504    // --------------------------------------------
505    // phase 2
506    size_t* size_list = NULL;
507    {
508        const size_t size_list_bytes = argc*sizeof(size_t);
509        if (size_list_bytes > _ALLOCA_S_THRESHOLD) {
510            return 1;
511        }
512        __try {
513            size_list = (size_t*)alloca(size_list_bytes);
514        } __except (GetExceptionCode() == STATUS_STACK_OVERFLOW ?
515                    EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
516            return 1;
517        }
518    }
519
520    // --------------------------------------------
521    // phase 3
522    char** argv = NULL;
523    {
524        get_size_list(line, size_list, argc);
525        const size_t argv_bytes = argc*sizeof(char*);
526        if (argv_bytes > _ALLOCA_S_THRESHOLD) {
527            return 1;
528        }
529        __try {
530            argv = (char**)alloca(argv_bytes);
531        } __except (GetExceptionCode() == STATUS_STACK_OVERFLOW ?
532                    EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
533            return 1;
534        }
535    }
536
537    // --------------------------------------------
538    // phase 4
539    {
540        size_t argv_total_bytes = 0;
541        for (size_t i = 0; i < argc; i++) {
542            argv_total_bytes += size_list[i];
543        }
544        if (argv_total_bytes > _ALLOCA_S_THRESHOLD) {
545            return 1;
546        }
547        char* argv_pool = NULL;
548        __try {
549            argv_pool = (char*)alloca(argv_total_bytes);
550        } __except (GetExceptionCode() == STATUS_STACK_OVERFLOW ?
551                    EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
552            return 1;
553        }
554        for (size_t i = 0; i < argc; i++) {
555            argv[i] = argv_pool;
556            argv_pool += size_list[i];
557        }
558        get_argv(line, size_list, argv, argc);
559    }
560    return check_args2(argc, argv);
561}
562#endif
563
564}
565#endif
Note: See TracBrowser for help on using the browser.