source: lab.git/Dev/utvpn/utvpn-unix-v101-7101-public/src/Mayaqua/Win32.c @ a1bae3e

trunk
Last change on this file since a1bae3e was a1bae3e, checked in by mitty <mitty@…>, 12 years ago
  • copy vendor drop to trunk

git-svn-id: https://lab.mitty.jp/svn/lab/trunk@147 7d2118f6-f56c-43e7-95a2-4bb3031d96e7

  • Property mode set to 100644
File size: 62.3 KB
Line 
1// SoftEther UT-VPN SourceCode
2//
3// Copyright (C) 2004-2010 SoftEther Corporation.
4// Copyright (C) 2004-2010 University of Tsukuba, Japan.
5// Copyright (C) 2003-2010 Daiyuu Nobori.
6// All Rights Reserved.
7//
8// http://utvpn.tsukuba.ac.jp/
9//
10// This program is free software; you can redistribute it and/or
11// modify it under the terms of the GNU General Public License
12// version 2 as published by the Free Software Foundation.
13//
14// This program is distributed in the hope that it will be useful,
15// but WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17// GNU General Public License for more details.
18//
19// You should have received a copy of the GNU General Public License version 2
20// along with this program; if not, write to the Free Software
21// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22//
23// このファイルは GPL バージョン 2 ライセンスで公開されています。
24// 誰でもこのファイルの内容を複製、改変したり、改変したバージョンを再配布
25// することができます。ただし、原著作物を改変した場合は、原著作物の著作権表示
26// を除去することはできません。改変した著作物を配布する場合は、改変実施者の
27// 著作権表示を原著作物の著作権表示に付随して記載するようにしてください。
28//
29// この SoftEther UT-VPN オープンソース・プロジェクトは、日本国の
30// ソフトイーサ株式会社 (SoftEther Corporation, http://www.softether.co.jp/ )
31// および筑波大学 (University of Tsukuba, http://www.tsukuba.ac.jp/ ) によって
32// ホストされています。
33// 本プログラムの配布者は、本プログラムを、業としての利用以外のため、
34// および、試験または研究のために利用が行われることを想定して配布
35// しています。
36// SoftEther UT-VPN プロジェクトの Web サイトは http://utvpn.tsukuba.ac.jp/ に
37// あります。
38// 本ソフトウェアの不具合の修正、機能改良、セキュリティホールの修復などのコード
39// の改変を行った場合で、その成果物を SoftEther UT-VPN プロジェクトに提出して
40// いただける場合は、 http://utvpn.tsukuba.ac.jp/ までソースコードを送付して
41// ください。SoftEther UT-VPN プロジェクトの本体リリースまたはブランチリリース
42// に組み込みさせていただきます。
43//
44// GPL に基づいて原著作物が提供される本ソフトウェアの改良版を配布、販売する
45// 場合は、そのソースコードを GPL に基づいて誰にでも開示する義務が生じます。
46//
47// 本ソフトウェアに関連する著作権、特許権、商標権はソフトイーサ株式会社
48// (SoftEther Corporation) およびその他の著作権保持者が保有しています。
49// ソフトイーサ株式会社等はこれらの権利を放棄していません。本ソフトウェアの
50// 二次著作物を配布、販売する場合は、これらの権利を侵害しないようにご注意
51// ください。
52//
53// お願い: どのような通信ソフトウェアにも通常は必ず未発見の
54// セキュリティホールが潜んでいます。本ソースコードをご覧いただいた結果、
55// UT-VPN にセキュリティホールを発見された場合は、当該セキュリティホールの
56// 情報を不特定多数に開示される前に、必ず、ソフトイーサ株式会社
57// および脆弱性情報の届出を受け付ける公的機関まで通報いただき、
58// 公益保護にご協力いただきますようお願い申し上げます。
59//
60// ソフトイーサ株式会社は、当該セキュリティホールについて迅速に対処を
61// 行い、UT-VPN および UT-VPN に関連するソフトウェアのユーザー・顧客
62// を保護するための努力を行います。
63//
64// ソフトイーサへの届出先: http://www.softether.co.jp/jp/contact/
65// 日本国内の脆弱性情報届出受付公的機関:
66//         独立行政法人 情報処理推進機構
67//         http://www.ipa.go.jp/security/vuln/report/
68//
69// 上記各事項について不明な点は、ソフトイーサ株式会社までご連絡ください。
70// 連絡先: http://www.softether.co.jp/jp/contact/
71
72// -----------------------------------------------
73// [ChangeLog]
74// 2010.05.20
75//  新規リリース by SoftEther
76// -----------------------------------------------
77
78// Win32.c
79// Microsoft Windows 依存コード
80
81#ifdef  WIN32
82
83#define _WIN32_WINNT        0x0502
84#define WINVER              0x0502
85#include <winsock2.h>
86#include <windows.h>
87#include <Dbghelp.h>
88#include <commctrl.h>
89#include <process.h>
90#include <stdio.h>
91#include <stdlib.h>
92#include <string.h>
93#include <wchar.h>
94#include <stdarg.h>
95#include <time.h>
96#include <errno.h>
97#include <Mayaqua/Mayaqua.h>
98
99static HANDLE heap_handle = NULL;
100static HANDLE hstdout = INVALID_HANDLE_VALUE;
101static HANDLE hstdin = INVALID_HANDLE_VALUE;
102
103// Win32 用スレッドデータ
104typedef struct WIN32THREAD
105{
106    HANDLE hThread;
107    DWORD thread_id;
108} WIN32THREAD;
109
110// Win32 用スレッド起動情報
111typedef struct WIN32THREADSTARTUPINFO
112{
113    THREAD_PROC *thread_proc;
114    void *param;
115    THREAD *thread;
116} WIN32THREADSTARTUPINFO;
117
118// Win32 用関数プロトタイプ
119DWORD CALLBACK Win32DefaultThreadProc(void *param);
120
121// 現在のプロセスハンドル
122static HANDLE hCurrentProcessHandle = NULL;
123static CRITICAL_SECTION fasttick_lock;
124static UINT64 start_tick = 0;
125static bool use_heap_api = false;
126static bool win32_is_nt = false;
127
128// Win32 用ファイル I/O データ
129typedef struct WIN32IO
130{
131    HANDLE hFile;
132    bool WriteMode;
133} WIN32IO;
134
135// Win32 用ミューテックスデータ
136typedef struct WIN32MUTEX
137{
138    HANDLE hMutex;
139} WIN32MUTEX;
140
141// ディスパッチテーブルの作成
142OS_DISPATCH_TABLE *Win32GetDispatchTable()
143{
144    static OS_DISPATCH_TABLE t =
145    {
146        Win32Init,
147        Win32Free,
148        Win32MemoryAlloc,
149        Win32MemoryReAlloc,
150        Win32MemoryFree,
151        Win32GetTick,
152        Win32GetSystemTime,
153        Win32Inc32,
154        Win32Dec32,
155        Win32Sleep,
156        Win32NewLock,
157        Win32Lock,
158        Win32Unlock,
159        Win32DeleteLock,
160        Win32InitEvent,
161        Win32SetEvent,
162        Win32ResetEvent,
163        Win32WaitEvent,
164        Win32FreeEvent,
165        Win32WaitThread,
166        Win32FreeThread,
167        Win32InitThread,
168        Win32ThreadId,
169        Win32FileOpen,
170        Win32FileOpenW,
171        Win32FileCreate,
172        Win32FileCreateW,
173        Win32FileWrite,
174        Win32FileRead,
175        Win32FileClose,
176        Win32FileFlush,
177        Win32FileSize,
178        Win32FileSeek,
179        Win32FileDelete,
180        Win32FileDeleteW,
181        Win32MakeDir,
182        Win32MakeDirW,
183        Win32DeleteDir,
184        Win32DeleteDirW,
185        Win32GetCallStack,
186        Win32GetCallStackSymbolInfo,
187        Win32FileRename,
188        Win32FileRenameW,
189        Win32Run,
190        Win32RunW,
191        Win32IsSupportedOs,
192        Win32GetOsInfo,
193        Win32Alert,
194        Win32AlertW,
195        Win32GetProductId,
196        Win32SetHighPriority,
197        Win32RestorePriority,
198        Win32NewSingleInstance,
199        Win32FreeSingleInstance,
200        Win32GetMemInfo,
201        Win32Yield,
202    };
203
204    return &t;
205}
206
207// 新しいスレッド用の初期化関数
208void Win32InitNewThread()
209{
210    static HINSTANCE hDll = NULL;
211    static bool (WINAPI *_SetThreadLocale)(LCID) = NULL;
212
213    if (hDll == NULL)
214    {
215        hDll = LoadLibrary("kernel32.dll");
216
217        _SetThreadLocale =
218            (bool (__stdcall *)(LCID))
219            GetProcAddress(hDll, "SetThreadLocale");
220    }
221
222    if (_SetThreadLocale != NULL)
223    {
224        _SetThreadLocale(LOCALE_USER_DEFAULT);
225    }
226}
227
228// フォルダの圧縮フラグを設定する
229bool Win32SetFolderCompressW(wchar_t *path, bool compressed)
230{
231    HANDLE h;
232    UINT retsize = 0;
233    USHORT flag;
234    wchar_t tmp[MAX_PATH];
235    // 引数チェック
236    if (path == NULL)
237    {
238        return false;
239    }
240
241    if (IsNt() == false)
242    {
243        char *path_a = CopyUniToStr(path);
244        bool ret = Win32SetFolderCompress(path_a, compressed);
245
246        Free(path_a);
247
248        return ret;
249    }
250
251    InnerFilePathW(tmp, sizeof(tmp), path);
252
253    // フォルダを開く
254    h = CreateFileW(tmp, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
255
256    if (h == INVALID_HANDLE_VALUE)
257    {
258        return false;
259    }
260
261    flag = compressed ? COMPRESSION_FORMAT_DEFAULT : COMPRESSION_FORMAT_NONE;
262
263    if (DeviceIoControl(h, FSCTL_SET_COMPRESSION, &flag, sizeof(USHORT),
264        NULL, 0, &retsize, NULL) == false)
265    {
266        return false;
267    }
268
269    CloseHandle(h);
270
271    return true;
272}
273bool Win32SetFolderCompress(char *path, bool compressed)
274{
275    HANDLE h;
276    UINT retsize = 0;
277    USHORT flag;
278    char tmp[MAX_PATH];
279    // 引数チェック
280    if (path == NULL)
281    {
282        return false;
283    }
284
285    InnerFilePath(tmp, sizeof(tmp), path);
286
287    // フォルダを開く
288    h = CreateFile(tmp, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
289
290    if (h == INVALID_HANDLE_VALUE)
291    {
292        return false;
293    }
294
295    flag = compressed ? COMPRESSION_FORMAT_DEFAULT : COMPRESSION_FORMAT_NONE;
296
297    if (DeviceIoControl(h, FSCTL_SET_COMPRESSION, &flag, sizeof(USHORT),
298        NULL, 0, &retsize, NULL) == false)
299    {
300        return false;
301    }
302
303    CloseHandle(h);
304
305    return true;
306}
307
308// ディスクの空き容量を取得する
309bool Win32GetDiskFreeW(wchar_t *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size)
310{
311    wchar_t tmp[MAX_SIZE];
312    UINT count = 0;
313    UINT i, n, len;
314    ULARGE_INTEGER v1, v2, v3;
315    bool ret = false;
316    // 引数チェック
317    if (path == NULL)
318    {
319        return false;
320    }
321
322    if (IsNt() == false)
323    {
324        bool ret;
325        char *path_a = CopyUniToStr(path);
326
327        ret = Win32GetDiskFree(path_a, free_size, used_size, total_size);
328
329        Free(path_a);
330
331        return ret;
332    }
333
334    Zero(&v1, sizeof(v1));
335    Zero(&v2, sizeof(v2));
336    Zero(&v3, sizeof(v3));
337
338    NormalizePathW(tmp, sizeof(tmp), path);
339
340    // ディレクトリ名を取得
341    if (UniStartWith(path, L"\\\\"))
342    {
343        count = 4;
344    }
345    else
346    {
347        count = 1;
348    }
349
350    len = UniStrLen(tmp);
351    n = 0;
352    for (i = 0;i < len;i++)
353    {
354        if (tmp[i] == L'\\')
355        {
356            n++;
357            if (n >= count)
358            {
359                tmp[i + 1] = 0;
360                break;
361            }
362        }
363    }
364
365    if (GetDiskFreeSpaceExW(tmp, &v1, &v2, &v3))
366    {
367        ret = true;
368    }
369
370    if (free_size != NULL)
371    {
372        *free_size = v1.QuadPart;
373    }
374
375    if (total_size != NULL)
376    {
377        *total_size = v2.QuadPart;
378    }
379
380    if (used_size != NULL)
381    {
382        *used_size = v2.QuadPart - v1.QuadPart;
383    }
384
385    return ret;
386}
387bool Win32GetDiskFree(char *path, UINT64 *free_size, UINT64 *used_size, UINT64 *total_size)
388{
389    char tmp[MAX_SIZE];
390    UINT count = 0;
391    UINT i, n, len;
392    ULARGE_INTEGER v1, v2, v3;
393    bool ret = false;
394    // 引数チェック
395    if (path == NULL)
396    {
397        return false;
398    }
399
400    Zero(&v1, sizeof(v1));
401    Zero(&v2, sizeof(v2));
402    Zero(&v3, sizeof(v3));
403
404    NormalizePath(tmp, sizeof(tmp), path);
405
406    // ディレクトリ名を取得
407    if (StartWith(path, "\\\\"))
408    {
409        count = 4;
410    }
411    else
412    {
413        count = 1;
414    }
415
416    len = StrLen(tmp);
417    n = 0;
418    for (i = 0;i < len;i++)
419    {
420        if (tmp[i] == '\\')
421        {
422            n++;
423            if (n >= count)
424            {
425                tmp[i + 1] = 0;
426                break;
427            }
428        }
429    }
430
431    if (GetDiskFreeSpaceEx(tmp, &v1, &v2, &v3))
432    {
433        ret = true;
434    }
435
436    if (free_size != NULL)
437    {
438        *free_size = v1.QuadPart;
439    }
440
441    if (total_size != NULL)
442    {
443        *total_size = v2.QuadPart;
444    }
445
446    if (used_size != NULL)
447    {
448        *used_size = v2.QuadPart - v1.QuadPart;
449    }
450
451    return ret;
452}
453
454// ディレクトリの列挙
455DIRLIST *Win32EnumDirEx(char *dirname, COMPARE *compare)
456{
457    DIRLIST *ret;
458    wchar_t *dirname_w = CopyStrToUni(dirname);
459
460    ret = Win32EnumDirExW(dirname_w, compare);
461
462    Free(dirname_w);
463
464    return ret;
465}
466DIRLIST *Win32EnumDirExW(wchar_t *dirname, COMPARE *compare)
467{
468    WIN32_FIND_DATAA data_a;
469    WIN32_FIND_DATAW data_w;
470    HANDLE h;
471    wchar_t tmp[MAX_PATH];
472    wchar_t tmp2[MAX_PATH];
473    wchar_t dirname2[MAX_PATH];
474    LIST *o;
475    DIRLIST *d;
476
477    UniStrCpy(tmp2, sizeof(tmp2), dirname);
478
479    if (UniStrLen(tmp2) >= 1 && tmp[UniStrLen(tmp2) - 1] == L'\\')
480    {
481        tmp2[UniStrLen(tmp2) - 1] = 0;
482    }
483
484    UniFormat(tmp, sizeof(tmp), L"%s\\*.*", tmp2);
485    NormalizePathW(tmp, sizeof(tmp), tmp);
486    NormalizePathW(dirname2, sizeof(dirname2), tmp2);
487
488    o = NewListFast(compare);
489
490    Zero(&data_a, sizeof(data_a));
491    Zero(&data_w, sizeof(data_w));
492
493    if (IsNt())
494    {
495        h = FindFirstFileW(tmp, &data_w);
496    }
497    else
498    {
499        char *tmp_a = CopyUniToStr(tmp);
500
501        h = FindFirstFileA(tmp_a, &data_a);
502
503        Free(tmp_a);
504    }
505
506    if (h != INVALID_HANDLE_VALUE)
507    {
508        bool b = true;
509
510        do
511        {
512            if (IsNt() == false)
513            {
514                Zero(&data_w, sizeof(data_w));
515                StrToUni(data_w.cFileName, sizeof(data_w.cFileName), data_a.cFileName);
516                data_w.dwFileAttributes = data_a.dwFileAttributes;
517                data_w.ftCreationTime = data_a.ftCreationTime;
518                data_w.ftLastWriteTime = data_a.ftLastWriteTime;
519                data_w.nFileSizeHigh = data_a.nFileSizeHigh;
520                data_w.nFileSizeLow = data_a.nFileSizeLow;
521            }
522
523            if (UniStrCmpi(data_w.cFileName, L"..") != 0 &&
524                UniStrCmpi(data_w.cFileName, L".") != 0)
525            {
526                DIRENT *f = ZeroMalloc(sizeof(DIRENT));
527                SYSTEMTIME t1, t2;
528                wchar_t fullpath[MAX_SIZE];
529                bool ok = false;
530
531                f->FileNameW = UniCopyStr(data_w.cFileName);
532                f->FileName = CopyUniToStr(f->FileNameW);
533                f->Folder = (data_w.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? true : false;
534
535                CombinePathW(fullpath, sizeof(fullpath), dirname2, f->FileNameW);
536
537                // ファイル情報の取得を試行する
538                if (MsIsNt())
539                {
540                    HANDLE h = CreateFileW(fullpath, 0,
541                        FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
542                        NULL, OPEN_EXISTING, 0, NULL);
543
544                    if (h != INVALID_HANDLE_VALUE)
545                    {
546                        BY_HANDLE_FILE_INFORMATION info;
547
548                        Zero(&info, sizeof(info));
549
550                        if (MsGetFileInformation(h, &info))
551                        {
552                            Zero(&t1, sizeof(t1));
553                            Zero(&t2, sizeof(t2));
554                            FileTimeToSystemTime(&info.ftCreationTime, &t1);
555                            FileTimeToSystemTime(&info.ftLastWriteTime, &t2);
556                            f->CreateDate = SystemToUINT64(&t1);
557                            f->UpdateDate = SystemToUINT64(&t2);
558
559                            if (f->Folder == false)
560                            {
561                                f->FileSize = ((UINT64)info.nFileSizeHigh * (UINT64)((UINT64)MAXDWORD + (UINT64)1)) + (UINT64)info.nFileSizeLow;
562                            }
563
564                            ok = true;
565                        }
566
567                        CloseHandle(h);
568                    }
569                }
570
571                if (ok == false)
572                {
573                    Zero(&t1, sizeof(t1));
574                    Zero(&t2, sizeof(t2));
575                    FileTimeToSystemTime(&data_w.ftCreationTime, &t1);
576                    FileTimeToSystemTime(&data_w.ftLastWriteTime, &t2);
577                    f->CreateDate = SystemToUINT64(&t1);
578                    f->UpdateDate = SystemToUINT64(&t2);
579
580                    if (f->Folder == false)
581                    {
582                        f->FileSize = ((UINT64)data_w.nFileSizeHigh * (UINT64)((UINT64)MAXDWORD + (UINT64)1)) + (UINT64)data_w.nFileSizeLow;
583                    }
584                }
585
586                Add(o, f);
587            }
588
589            Zero(&data_w, sizeof(data_w));
590            Zero(&data_a, sizeof(data_a));
591
592            if (IsNt())
593            {
594                b = FindNextFileW(h, &data_w);
595            }
596            else
597            {
598                b = FindNextFileA(h, &data_a);
599            }
600        }
601        while (b);
602
603        FindClose(h);
604    }
605
606    Sort(o);
607
608    d = ZeroMalloc(sizeof(DIRLIST));
609    d->NumFiles = LIST_NUM(o);
610    d->File = ToArray(o);
611
612    ReleaseList(o);
613
614    return d;
615}
616
617// EXE ファイル名を取得
618void Win32GetExeNameW(wchar_t *name, UINT size)
619{
620    // 引数チェック
621    if (name == NULL)
622    {
623        return;
624    }
625
626    if (IsNt() == false)
627    {
628        char name_a[MAX_PATH];
629
630        Win32GetExeName(name_a, sizeof(name_a));
631
632        StrToUni(name, size, name_a);
633
634        return;
635    }
636
637    UniStrCpy(name, size, L"");
638
639    GetModuleFileNameW(NULL, name, size);
640}
641void Win32GetExeName(char *name, UINT size)
642{
643    // 引数チェック
644    if (name == NULL)
645    {
646        return;
647    }
648
649    StrCpy(name, size, "");
650
651    GetModuleFileName(NULL, name, size);
652}
653
654// 現在のディレクトリの取得
655void Win32GetCurrentDirW(wchar_t *dir, UINT size)
656{
657    // 引数チェック
658    if (dir == NULL)
659    {
660        return;
661    }
662
663    if (IsNt() == false)
664    {
665        char dir_a[MAX_PATH];
666
667        Win32GetCurrentDir(dir_a, sizeof(dir_a));
668
669        StrToUni(dir, size, dir_a);
670
671        return;
672    }
673
674    GetCurrentDirectoryW(size, dir);
675}
676void Win32GetCurrentDir(char *dir, UINT size)
677{
678    // 引数チェック
679    if (dir == NULL)
680    {
681        return;
682    }
683
684    GetCurrentDirectory(size, dir);
685}
686
687// イールド
688void Win32Yield()
689{
690    Sleep(0);
691}
692
693// メモリ情報の取得
694void Win32GetMemInfo(MEMINFO *info)
695{
696    MEMORYSTATUS st;
697    // 引数チェック
698    if (info == NULL)
699    {
700        return;
701    }
702
703    Zero(info, sizeof(MEMINFO));
704    Zero(&st, sizeof(st));
705    st.dwLength = sizeof(st);
706
707    GlobalMemoryStatus(&st);
708
709    // 論理メモリ量
710    info->TotalMemory = (UINT64)st.dwTotalPageFile;
711    info->FreeMemory = (UINT64)st.dwAvailPageFile;
712    info->UsedMemory = info->TotalMemory - info->FreeMemory;
713
714    // 物理メモリ量
715    info->TotalPhys = (UINT64)st.dwTotalPhys;
716    info->FreePhys = (UINT64)st.dwAvailPhys;
717    info->UsedPhys = info->TotalPhys - info->FreePhys;
718}
719
720// シングルインスタンスの作成
721void *Win32NewSingleInstance(char *instance_name)
722{
723    WIN32MUTEX *ret;
724    char tmp[MAX_SIZE];
725    HANDLE hMutex;
726    // 引数チェック
727    if (instance_name == NULL)
728    {
729        char exe_path[MAX_PATH];
730        GetModuleFileName(NULL, exe_path, sizeof(exe_path));
731        HashInstanceName(tmp, sizeof(tmp), exe_path);
732        instance_name = tmp;
733    }
734
735    hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, instance_name);
736    if (hMutex != NULL)
737    {
738        CloseHandle(hMutex);
739        return NULL;
740    }
741
742    hMutex = CreateMutex(NULL, FALSE, instance_name);
743    if (hMutex == NULL)
744    {
745        CloseHandle(hMutex);
746        return NULL;
747    }
748
749    ret = Win32MemoryAlloc(sizeof(WIN32MUTEX));
750    ret->hMutex = hMutex;
751
752    return (void *)ret;
753}
754
755// シングルインスタンスの解放
756void Win32FreeSingleInstance(void *data)
757{
758    WIN32MUTEX *m;
759    // 引数チェック
760    if (data == NULL)
761    {
762        return;
763    }
764
765    m = (WIN32MUTEX *)data;
766    ReleaseMutex(m->hMutex);
767    CloseHandle(m->hMutex);
768
769    Win32MemoryFree(m);
770}
771
772// 優先順位を高くする
773void Win32SetHighPriority()
774{
775    SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
776}
777
778// 優先順位を戻す
779void Win32RestorePriority()
780{
781    SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
782}
783
784// ノード情報を取得
785char* Win32GetProductId()
786{
787    char *product_id;
788
789    return CopyStr("--");
790
791    // プロダクト ID
792    product_id = MsRegReadStr(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "ProductId");
793    if (product_id == NULL)
794    {
795        product_id = MsRegReadStr(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion", "ProductId");
796    }
797
798    return product_id;
799}
800
801// 現在サポートされている OS かどうか取得
802bool Win32IsSupportedOs()
803{
804    if (Win32GetOsType() == 0)
805    {
806        Win32Alert(
807            "SoftEther UT-VPN doesn't support this Windows Operating System.\n"
808            "SoftEther UT-VPN requires " SUPPORTED_WINDOWS_LIST ".\n\n"
809            "Please contact your system administrator.", NULL);
810        return false;
811    }
812
813    return true;
814}
815
816// アラートの表示
817void Win32AlertW(wchar_t *msg, wchar_t *caption)
818{
819    char *s;
820    // 引数チェック
821    if (msg == NULL)
822    {
823        msg = L"Alert";
824    }
825    if (caption == NULL)
826    {
827        caption = L"SoftEther UT-VPN Kernel";
828    }
829
830    s = GetCommandLineStr();
831
832    if (SearchStr(s, "win9x_uninstall", 0) == INFINITE && SearchStr(s, "win9x_install", 0) == INFINITE)
833    {
834        // Win9x サービスモードのアンインストール時には非表示とする
835        MessageBoxW(NULL, msg, caption, MB_SETFOREGROUND | MB_TOPMOST | MB_SERVICE_NOTIFICATION | MB_OK | MB_ICONEXCLAMATION);
836    }
837
838    Free(s);
839}
840void Win32Alert(char *msg, char *caption)
841{
842    char *s;
843    // 引数チェック
844    if (msg == NULL)
845    {
846        msg = "Alert";
847    }
848    if (caption == NULL)
849    {
850        caption = "SoftEther UT-VPN Kernel";
851    }
852
853    s = GetCommandLineStr();
854
855    if (SearchStr(s, "win9x_uninstall", 0) == INFINITE && SearchStr(s, "win9x_install", 0) == INFINITE)
856    {
857        // Win9x サービスモードのアンインストール時には非表示とする
858        MessageBox(NULL, msg, caption, MB_SETFOREGROUND | MB_TOPMOST | MB_SERVICE_NOTIFICATION | MB_OK | MB_ICONEXCLAMATION);
859    }
860
861    Free(s);
862}
863void Win32DebugAlert(char *msg)
864{
865    // 引数チェック
866    if (msg == NULL)
867    {
868        msg = "Alert";
869    }
870
871    MessageBox(NULL, msg, "Debug", MB_SETFOREGROUND | MB_TOPMOST | MB_SERVICE_NOTIFICATION | MB_OK | MB_ICONEXCLAMATION);
872}
873
874// OS 情報の取得
875void Win32GetOsInfo(OS_INFO *info)
876{
877    UINT type = Win32GetOsType();
878    OSVERSIONINFOEX os;
879    char tmp[MAX_SIZE];
880    // 引数チェック
881    if (info == NULL)
882    {
883        return;
884    }
885
886    Zero(&os, sizeof(os));
887    os.dwOSVersionInfoSize = sizeof(os);
888    GetVersionEx((LPOSVERSIONINFOA)&os);
889
890    info->OsType = Win32GetOsType();
891    info->OsServicePack = os.wServicePackMajor;
892    if (OS_IS_WINDOWS_NT(info->OsType))
893    {
894        char *s;
895        char *keyname = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion";
896        info->OsSystemName = CopyStr("Windows NT");
897        Format(tmp, sizeof(tmp), "Build %u", os.dwBuildNumber);
898        if (s = MsRegReadStr(REG_LOCAL_MACHINE, keyname, "CurrentType"))
899        {
900            char str[MAX_SIZE];
901            Format(str, sizeof(str), ", %s", s);
902            StrCat(tmp, sizeof(tmp), str);
903            Free(s);
904        }
905        if (os.wServicePackMajor != 0)
906        {
907            char str[MAX_SIZE];
908            Format(str, sizeof(str), ", Service Pack %u", os.wServicePackMajor);
909            StrCat(tmp, sizeof(tmp), str);
910        }
911        if (s = MsRegReadStr(REG_LOCAL_MACHINE, keyname, "BuildLab"))
912        {
913            char str[MAX_SIZE];
914            Format(str, sizeof(str), " (%s)", s);
915            StrCat(tmp, sizeof(tmp), str);
916            Free(s);
917        }
918        info->OsVersion = CopyStr(tmp);
919        info->KernelName = CopyStr("NTOS Kernel");
920        Format(tmp, sizeof(tmp), "Build %u", os.dwBuildNumber);
921        if (s = MsRegReadStr(REG_LOCAL_MACHINE, keyname, "CurrentType"))
922        {
923            char str[MAX_SIZE];
924            Format(str, sizeof(str), " %s", s);
925            StrCat(tmp, sizeof(tmp), str);
926            Free(s);
927        }
928        info->KernelVersion = CopyStr(tmp);
929    }
930    else
931    {
932        OSVERSIONINFO os;
933        Zero(&os, sizeof(os));
934        os.dwOSVersionInfoSize = sizeof(os);
935        GetVersionEx(&os);
936        Format(tmp, sizeof(tmp), "Build %u %s", LOWORD(os.dwBuildNumber), os.szCSDVersion);
937        Trim(tmp);
938        info->OsVersion = CopyStr(tmp);
939        info->OsSystemName = CopyStr("Windows");
940        info->KernelName = CopyStr("Windows 9x Kernel");
941        info->KernelVersion = CopyStr(tmp);
942    }
943
944    info->OsProductName = CopyStr(OsTypeToStr(info->OsType));
945    info->OsVendorName = CopyStr("Microsoft Corporation");
946}
947
948// Windows NT かどうか取得
949bool Win32IsNt()
950{
951    OSVERSIONINFO os;
952    Zero(&os, sizeof(os));
953    os.dwOSVersionInfoSize = sizeof(os);
954
955    if (GetVersionEx(&os) == FALSE)
956    {
957        // 失敗?
958        return false;
959    }
960
961    if (os.dwPlatformId == VER_PLATFORM_WIN32_NT)
962    {
963        // NT
964        return true;
965    }
966
967    // 9x
968    return false;
969}
970
971// OS 種類の取得
972UINT Win32GetOsType()
973{
974    OSVERSIONINFO os;
975    Zero(&os, sizeof(os));
976    os.dwOSVersionInfoSize = sizeof(os);
977
978    if (GetVersionEx(&os) == FALSE)
979    {
980        // 失敗?
981        return 0;
982    }
983
984    if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
985    {
986        // Windows 9x 系
987        if (os.dwMajorVersion == 4)
988        {
989            if (os.dwMinorVersion == 0)
990            {
991                return OSTYPE_WINDOWS_95;
992            }
993            else if (os.dwMinorVersion == 10)
994            {
995                return OSTYPE_WINDOWS_98;
996            }
997            else if (os.dwMinorVersion == 90)
998            {
999                return OSTYPE_WINDOWS_ME;
1000            }
1001            else
1002            {
1003                return OSTYPE_WINDOWS_UNKNOWN;
1004            }
1005        }
1006        else if (os.dwMajorVersion >= 5)
1007        {
1008            return OSTYPE_WINDOWS_UNKNOWN;
1009        }
1010    }
1011    else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT)
1012    {
1013        UINT sp = Win32GetSpVer(os.szCSDVersion);
1014        if (os.dwMajorVersion == 4)
1015        {
1016            if (sp < 6)
1017            {
1018                // SP6 以前
1019                return 0;
1020            }
1021        }
1022        if (os.dwMajorVersion < 4)
1023        {
1024            // NT 3.51 以前
1025            return 0;
1026        }
1027        else
1028        {
1029            OSVERSIONINFOEX os;
1030            Zero(&os, sizeof(os));
1031            os.dwOSVersionInfoSize = sizeof(os);
1032            GetVersionEx((LPOSVERSIONINFOA)&os);
1033
1034            if (os.dwMajorVersion == 4)
1035            {
1036                // Windows NT 4.0
1037                if (os.wProductType == VER_NT_DOMAIN_CONTROLLER || os.wProductType == VER_NT_SERVER)
1038                {
1039                    if ((os.wSuiteMask & VER_SUITE_TERMINAL) || (os.wSuiteMask & VER_SUITE_SINGLEUSERTS))
1040                    {
1041                        return OSTYPE_WINDOWS_NT_4_TERMINAL_SERVER;
1042                    }
1043                    if (os.wSuiteMask & VER_SUITE_ENTERPRISE)
1044                    {
1045                        return OSTYPE_WINDOWS_NT_4_SERVER_ENTERPRISE;
1046                    }
1047                    if (os.wSuiteMask & VER_SUITE_BACKOFFICE)
1048                    {
1049                        return OSTYPE_WINDOWS_NT_4_BACKOFFICE;
1050                    }
1051                    if ((os.wSuiteMask & VER_SUITE_SMALLBUSINESS) || (os.wSuiteMask & VER_SUITE_SMALLBUSINESS_RESTRICTED))
1052                    {
1053                        return OSTYPE_WINDOWS_NT_4_SMS;
1054                    }
1055                    else
1056                    {
1057                        return OSTYPE_WINDOWS_NT_4_SERVER;
1058                    }
1059                }
1060                else
1061                {
1062                    return OSTYPE_WINDOWS_NT_4_WORKSTATION;
1063                }
1064            }
1065            else if (os.dwMajorVersion == 5)
1066            {
1067                // Windows 2000, XP, Server 2003
1068                if (os.dwMinorVersion == 0)
1069                {
1070                    // Windows 2000
1071                    if (os.wProductType == VER_NT_DOMAIN_CONTROLLER || os.wProductType == VER_NT_SERVER)
1072                    {
1073                        // Server
1074                        if (os.wSuiteMask & VER_SUITE_DATACENTER)
1075                        {
1076                            return OSTYPE_WINDOWS_2000_DATACENTER_SERVER;
1077                        }
1078                        else if ((os.wSuiteMask & VER_SUITE_SMALLBUSINESS) || (os.wSuiteMask & VER_SUITE_SMALLBUSINESS_RESTRICTED))
1079                        {
1080                            return OSTYPE_WINDOWS_2000_SBS;
1081                        }
1082                        else if (os.wSuiteMask & VER_SUITE_BACKOFFICE)
1083                        {
1084                            return OSTYPE_WINDOWS_2000_BACKOFFICE;
1085                        }
1086                        else if (os.wSuiteMask & VER_SUITE_ENTERPRISE)
1087                        {
1088                            return OSTYPE_WINDOWS_2000_ADVANCED_SERVER;
1089                        }
1090                        else
1091                        {
1092                            return OSTYPE_WINDOWS_2000_SERVER;
1093                        }
1094                    }
1095                    else
1096                    {
1097                        // Client
1098                        return OSTYPE_WINDOWS_2000_PROFESSIONAL;
1099                    }
1100                }
1101                else if (os.dwMinorVersion == 1)
1102                {
1103                    // Windows XP
1104                    if (os.wSuiteMask & VER_SUITE_PERSONAL)
1105                    {
1106                        return OSTYPE_WINDOWS_XP_HOME;
1107                    }
1108                    else
1109                    {
1110                        return OSTYPE_WINDOWS_XP_PROFESSIONAL;
1111                    }
1112                }
1113                else if (os.dwMinorVersion == 2)
1114                {
1115                    // Windows Server 2003
1116                    if (os.wProductType == VER_NT_DOMAIN_CONTROLLER || os.wProductType == VER_NT_SERVER)
1117                    {
1118                        // Server
1119                        if (os.wSuiteMask & VER_SUITE_DATACENTER)
1120                        {
1121                            return OSTYPE_WINDOWS_2003_DATACENTER;
1122                        }
1123                        else if ((os.wSuiteMask & VER_SUITE_SMALLBUSINESS) || (os.wSuiteMask & VER_SUITE_SMALLBUSINESS_RESTRICTED))
1124                        {
1125                            return OSTYPE_WINDOWS_2003_SBS;
1126                        }
1127                        else if (os.wSuiteMask & VER_SUITE_BACKOFFICE)
1128                        {
1129                            return OSTYPE_WINDOWS_2003_BACKOFFICE;
1130                        }
1131                        else if (os.wSuiteMask & VER_SUITE_ENTERPRISE)
1132                        {
1133                            return OSTYPE_WINDOWS_2003_ENTERPRISE;
1134                        }
1135                        else if (os.wSuiteMask & VER_SUITE_BLADE)
1136                        {
1137                            return OSTYPE_WINDOWS_2003_WEB;
1138                        }
1139                        else
1140                        {
1141                            return OSTYPE_WINDOWS_2003_STANDARD;
1142                        }
1143                    }
1144                    else
1145                    {
1146                        // Client (Unknown XP?)
1147                        return OSTYPE_WINDOWS_XP_PROFESSIONAL;
1148                    }
1149                }
1150                else
1151                {
1152                    // Windows Longhorn
1153                    if (os.wProductType == VER_NT_DOMAIN_CONTROLLER || os.wProductType == VER_NT_SERVER)
1154                    {
1155                        return OSTYPE_WINDOWS_LONGHORN_SERVER;
1156                    }
1157                    else
1158                    {
1159                        return OSTYPE_WINDOWS_LONGHORN_PROFESSIONAL;
1160                    }
1161                }
1162            }
1163            else
1164            {
1165                if (os.dwMajorVersion == 6 && os.dwMinorVersion == 0)
1166                {
1167                    // Windows Vista, Server 2008
1168                    if (os.wProductType == VER_NT_DOMAIN_CONTROLLER || os.wProductType == VER_NT_SERVER)
1169                    {
1170                        return OSTYPE_WINDOWS_LONGHORN_SERVER;
1171                    }
1172                    else
1173                    {
1174                        return OSTYPE_WINDOWS_LONGHORN_PROFESSIONAL;
1175                    }
1176                }
1177                else if (os.dwMajorVersion == 6 && os.dwMinorVersion == 1)
1178                {
1179                    if (os.wProductType == VER_NT_WORKSTATION)
1180                    {
1181                        // Windows 7
1182                        return OSTYPE_WINDOWS_7;
1183                    }
1184                    else
1185                    {
1186                        // Windows Server 2008 R2
1187                        return OSTYPE_WINDOWS_SERVER_2008_R2;
1188                    }
1189                }
1190                else
1191                {
1192                    if (os.wProductType == VER_NT_WORKSTATION)
1193                    {
1194                        // Windows 8
1195                        return OSTYPE_WINDOWS_8;
1196                    }
1197                    else
1198                    {
1199                        // Windows Server 8
1200                        return OSTYPE_WINDOWS_SERVER_2008_R2;
1201                    }
1202                }
1203            }
1204        }
1205    }
1206
1207    // 判別できない
1208    return 0;
1209}
1210
1211// 文字列から SP のバージョンを取得する
1212UINT Win32GetSpVer(char *str)
1213{
1214    UINT ret, i;
1215    TOKEN_LIST *t;
1216    // 引数チェック
1217    if (str == NULL)
1218    {
1219        return 0;
1220    }
1221
1222    t = ParseToken(str, NULL);
1223    if (t == NULL)
1224    {
1225        return 0;
1226    }
1227
1228    ret = 0;
1229    for (i = 0;i < t->NumTokens;i++)
1230    {
1231        ret = ToInt(t->Token[i]);
1232        if (ret != 0)
1233        {
1234            break;
1235        }
1236    }
1237
1238    FreeToken(t);
1239
1240    return ret;
1241}
1242
1243// プロセスの強制終了
1244bool Win32TerminateProcess(void *handle)
1245{
1246    HANDLE h;
1247    // 引数チェック
1248    if (handle == NULL)
1249    {
1250        return false;
1251    }
1252
1253    h = (HANDLE)handle;
1254
1255    TerminateProcess(h, 0);
1256
1257    return true;
1258}
1259
1260// プロセスを閉じる
1261void Win32CloseProcess(void *handle)
1262{
1263    // 引数チェック
1264    if (handle == NULL)
1265    {
1266        return;
1267    }
1268
1269    CloseHandle((HANDLE)handle);
1270}
1271
1272// 指定されたプロセスが生きているかどうかチェック
1273bool Win32IsProcessAlive(void *handle)
1274{
1275    HANDLE h;
1276    // 引数チェック
1277    if (handle == NULL)
1278    {
1279        return false;
1280    }
1281
1282    h = (HANDLE)handle;
1283
1284    if (WaitForSingleObject(h, 0) == WAIT_OBJECT_0)
1285    {
1286        return false;
1287    }
1288
1289    return true;
1290}
1291
1292// プロセスの終了を待機する
1293bool Win32WaitProcess(void *h, UINT timeout)
1294{
1295    // 引数チェック
1296    if (h == NULL)
1297    {
1298        return false;
1299    }
1300    if (timeout == 0)
1301    {
1302        timeout = INFINITE;
1303    }
1304
1305    if (WaitForSingleObject((HANDLE)h, timeout) == WAIT_TIMEOUT)
1306    {
1307        return false;
1308    }
1309
1310    return true;
1311}
1312
1313// プロセスの起動 (ハンドルを返す)
1314void *Win32RunExW(wchar_t *filename, wchar_t *arg, bool hide)
1315{
1316    return Win32RunEx2W(filename, arg, hide, NULL);
1317}
1318void *Win32RunEx2W(wchar_t *filename, wchar_t *arg, bool hide, UINT *process_id)
1319{
1320    return Win32RunEx3W(filename, arg, hide, process_id, false);
1321}
1322void *Win32RunEx3W(wchar_t *filename, wchar_t *arg, bool hide, UINT *process_id, bool disableWow)
1323{
1324    STARTUPINFOW info;
1325    PROCESS_INFORMATION ret;
1326    wchar_t cmdline[MAX_SIZE];
1327    wchar_t name[MAX_PATH];
1328    void *p;
1329    // 引数チェック
1330    if (filename == NULL)
1331    {
1332        return NULL;
1333    }
1334
1335    if (IsNt() == false)
1336    {
1337        char *filename_a = CopyUniToStr(filename);
1338        char *arg_a = CopyUniToStr(arg);
1339        void *ret = Win32RunEx(filename_a, arg_a, hide);
1340
1341        Free(filename_a);
1342        Free(arg_a);
1343
1344        return ret;
1345    }
1346
1347    UniStrCpy(name, sizeof(name), filename);
1348    UniTrim(name);
1349
1350    if (UniSearchStr(name, L"\"", 0) == INFINITE)
1351    {
1352        if (arg == NULL)
1353        {
1354            UniFormat(cmdline, sizeof(cmdline), L"%s", name);
1355        }
1356        else
1357        {
1358            UniFormat(cmdline, sizeof(cmdline), L"%s %s", name, arg);
1359        }
1360    }
1361    else
1362    {
1363        if (arg == NULL)
1364        {
1365            UniFormat(cmdline, sizeof(cmdline), L"\"%s\"", name);
1366        }
1367        else
1368        {
1369            UniFormat(cmdline, sizeof(cmdline), L"\"%s\" %s", name, arg);
1370        }
1371    }
1372
1373    Zero(&info, sizeof(info));
1374    Zero(&ret, sizeof(ret));
1375    info.cb = sizeof(info);
1376    info.dwFlags = STARTF_USESHOWWINDOW;
1377    info.wShowWindow = (hide == false ? SW_SHOWDEFAULT : SW_HIDE);
1378
1379    UniTrim(cmdline);
1380
1381    if (disableWow)
1382    {
1383        p = MsDisableWow64FileSystemRedirection();
1384    }
1385
1386    if (CreateProcessW(NULL, cmdline, NULL, NULL, FALSE,
1387        (hide == false ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW | CREATE_NEW_CONSOLE) | NORMAL_PRIORITY_CLASS,
1388        NULL, NULL, &info, &ret) == FALSE)
1389    {
1390        if (disableWow)
1391        {
1392            MsRestoreWow64FileSystemRedirection(p);
1393        }
1394        return NULL;
1395    }
1396
1397    if (disableWow)
1398    {
1399        MsRestoreWow64FileSystemRedirection(p);
1400    }
1401
1402    if (process_id != NULL)
1403    {
1404        *process_id = ret.dwProcessId;
1405    }
1406
1407    CloseHandle(ret.hThread);
1408    return ret.hProcess;
1409}
1410void *Win32RunEx(char *filename, char *arg, bool hide)
1411{
1412    return Win32RunEx2(filename, arg, hide, NULL);
1413}
1414void *Win32RunEx2(char *filename, char *arg, bool hide, UINT *process_id)
1415{
1416    return Win32RunEx3(filename, arg, hide, process_id, false);
1417}
1418void *Win32RunEx3(char *filename, char *arg, bool hide, UINT *process_id, bool disableWow)
1419{
1420    STARTUPINFO info;
1421    PROCESS_INFORMATION ret;
1422    char cmdline[MAX_SIZE];
1423    char name[MAX_PATH];
1424    void *p = NULL;
1425    // 引数チェック
1426    if (filename == NULL)
1427    {
1428        return NULL;
1429    }
1430
1431    StrCpy(name, sizeof(name), filename);
1432    Trim(name);
1433
1434    if (SearchStr(name, "\"", 0) == INFINITE)
1435    {
1436        if (arg == NULL)
1437        {
1438            Format(cmdline, sizeof(cmdline), "%s", name);
1439        }
1440        else
1441        {
1442            Format(cmdline, sizeof(cmdline), "%s %s", name, arg);
1443        }
1444    }
1445    else
1446    {
1447        if (arg == NULL)
1448        {
1449            Format(cmdline, sizeof(cmdline), "\"%s\"", name);
1450        }
1451        else
1452        {
1453            Format(cmdline, sizeof(cmdline), "\"%s\" %s", name, arg);
1454        }
1455    }
1456
1457    Zero(&info, sizeof(info));
1458    Zero(&ret, sizeof(ret));
1459    info.cb = sizeof(info);
1460    info.dwFlags = STARTF_USESHOWWINDOW;
1461    info.wShowWindow = (hide == false ? SW_SHOWDEFAULT : SW_HIDE);
1462
1463    Trim(cmdline);
1464
1465    if (disableWow)
1466    {
1467        p = MsDisableWow64FileSystemRedirection();
1468    }
1469
1470    if (CreateProcess(NULL, cmdline, NULL, NULL, FALSE,
1471        (hide == false ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW | CREATE_NEW_CONSOLE) | NORMAL_PRIORITY_CLASS,
1472        NULL, NULL, &info, &ret) == FALSE)
1473    {
1474        if (disableWow)
1475        {
1476            MsRestoreWow64FileSystemRedirection(p);
1477        }
1478        return NULL;
1479    }
1480    if (disableWow)
1481    {
1482        MsRestoreWow64FileSystemRedirection(p);
1483    }
1484
1485    if (process_id != NULL)
1486    {
1487        *process_id = ret.dwProcessId;
1488    }
1489
1490    CloseHandle(ret.hThread);
1491    return ret.hProcess;
1492}
1493
1494// プロセスの起動
1495bool Win32RunW(wchar_t *filename, wchar_t *arg, bool hide, bool wait)
1496{
1497    STARTUPINFOW info;
1498    PROCESS_INFORMATION ret;
1499    wchar_t cmdline[MAX_SIZE];
1500    wchar_t name[MAX_PATH];
1501    // 引数チェック
1502    if (filename == NULL)
1503    {
1504        return false;
1505    }
1506
1507    if (IsNt() == false)
1508    {
1509        char *filename_a = CopyUniToStr(filename);
1510        char *arg_a = CopyUniToStr(arg);
1511        bool ret;
1512
1513        ret = Win32Run(filename_a, arg_a, hide, wait);
1514
1515        Free(filename_a);
1516        Free(arg_a);
1517
1518        return ret;
1519    }
1520
1521    UniStrCpy(name, sizeof(name), filename);
1522    UniTrim(name);
1523
1524    if (UniSearchStr(name, L"\"", 0) == INFINITE)
1525    {
1526        if (arg == NULL)
1527        {
1528            UniFormat(cmdline, sizeof(cmdline), L"%s", name);
1529        }
1530        else
1531        {
1532            UniFormat(cmdline, sizeof(cmdline), L"%s %s", name, arg);
1533        }
1534    }
1535    else
1536    {
1537        if (arg == NULL)
1538        {
1539            UniFormat(cmdline, sizeof(cmdline), L"\"%s\"", name);
1540        }
1541        else
1542        {
1543            UniFormat(cmdline, sizeof(cmdline), L"\"%s\" %s", name, arg);
1544        }
1545    }
1546
1547    Zero(&info, sizeof(info));
1548    Zero(&ret, sizeof(ret));
1549    info.cb = sizeof(info);
1550    info.dwFlags = STARTF_USESHOWWINDOW;
1551    info.wShowWindow = (hide == false ? SW_SHOWDEFAULT : SW_HIDE);
1552
1553    UniTrim(cmdline);
1554
1555    if (CreateProcessW(NULL, cmdline, NULL, NULL, FALSE,
1556        (hide == false ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW | CREATE_NEW_CONSOLE) | NORMAL_PRIORITY_CLASS,
1557        NULL, NULL, &info, &ret) == FALSE)
1558    {
1559        return false;
1560    }
1561
1562    if (wait)
1563    {
1564        WaitForSingleObject(ret.hProcess, INFINITE);
1565    }
1566
1567    CloseHandle(ret.hThread);
1568    CloseHandle(ret.hProcess);
1569
1570    return true;
1571}
1572bool Win32Run(char *filename, char *arg, bool hide, bool wait)
1573{
1574    STARTUPINFO info;
1575    PROCESS_INFORMATION ret;
1576    char cmdline[MAX_SIZE];
1577    char name[MAX_PATH];
1578    // 引数チェック
1579    if (filename == NULL)
1580    {
1581        return false;
1582    }
1583
1584    StrCpy(name, sizeof(name), filename);
1585    Trim(name);
1586
1587    if (SearchStr(name, "\"", 0) == INFINITE)
1588    {
1589        if (arg == NULL)
1590        {
1591            Format(cmdline, sizeof(cmdline), "%s", name);
1592        }
1593        else
1594        {
1595            Format(cmdline, sizeof(cmdline), "%s %s", name, arg);
1596        }
1597    }
1598    else
1599    {
1600        if (arg == NULL)
1601        {
1602            Format(cmdline, sizeof(cmdline), "\"%s\"", name);
1603        }
1604        else
1605        {
1606            Format(cmdline, sizeof(cmdline), "\"%s\" %s", name, arg);
1607        }
1608    }
1609
1610    Zero(&info, sizeof(info));
1611    Zero(&ret, sizeof(ret));
1612    info.cb = sizeof(info);
1613    info.dwFlags = STARTF_USESHOWWINDOW;
1614    info.wShowWindow = (hide == false ? SW_SHOWDEFAULT : SW_HIDE);
1615
1616    Trim(cmdline);
1617
1618    if (CreateProcess(NULL, cmdline, NULL, NULL, FALSE,
1619        (hide == false ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW | CREATE_NEW_CONSOLE) | NORMAL_PRIORITY_CLASS,
1620        NULL, NULL, &info, &ret) == FALSE)
1621    {
1622        return false;
1623    }
1624
1625    if (wait)
1626    {
1627        WaitForSingleObject(ret.hProcess, INFINITE);
1628    }
1629
1630    CloseHandle(ret.hThread);
1631    CloseHandle(ret.hProcess);
1632
1633    return true;
1634}
1635
1636// スレッド ID の取得
1637UINT Win32ThreadId()
1638{
1639    return GetCurrentThreadId();
1640}
1641
1642// ファイル名の変更
1643bool Win32FileRenameW(wchar_t *old_name, wchar_t *new_name)
1644{
1645    // 引数チェック
1646    if (old_name == NULL || new_name == NULL)
1647    {
1648        return false;
1649    }
1650
1651    if (IsNt() == false)
1652    {
1653        char *old_name_a = CopyUniToStr(old_name);
1654        char *new_name_a = CopyUniToStr(new_name);
1655        bool ret = Win32FileRename(old_name_a, new_name_a);
1656
1657        Free(old_name_a);
1658        Free(new_name_a);
1659
1660        return ret;
1661    }
1662
1663    // リネーム
1664    if (MoveFileW(old_name, new_name) == FALSE)
1665    {
1666        return false;
1667    }
1668
1669    return true;
1670}
1671bool Win32FileRename(char *old_name, char *new_name)
1672{
1673    // 引数チェック
1674    if (old_name == NULL || new_name == NULL)
1675    {
1676        return false;
1677    }
1678
1679    // リネーム
1680    if (MoveFile(old_name, new_name) == FALSE)
1681    {
1682        return false;
1683    }
1684
1685    return true;
1686}
1687
1688// EXE ファイルが存在しているディレクトリ名を取得する
1689void Win32GetExeDirW(wchar_t *name, UINT size)
1690{
1691    wchar_t exe_path[MAX_SIZE];
1692    wchar_t exe_dir[MAX_SIZE];
1693    // 引数チェック
1694    if (name == NULL)
1695    {
1696        return;
1697    }
1698
1699    if (IsNt() == false)
1700    {
1701        char name_a[MAX_PATH];
1702
1703        Win32GetExeDir(name_a, sizeof(name_a));
1704
1705        StrToUni(name, size, name_a);
1706
1707        return;
1708    }
1709
1710    // EXE ファイル名を取得
1711    GetModuleFileNameW(NULL, exe_path, sizeof(exe_path));
1712
1713    // ディレクトリ名を取得
1714    Win32GetDirFromPathW(exe_dir, sizeof(exe_dir), exe_path);
1715
1716    UniStrCpy(name, size, exe_dir);
1717}
1718void Win32GetExeDir(char *name, UINT size)
1719{
1720    char exe_path[MAX_SIZE];
1721    char exe_dir[MAX_SIZE];
1722    // 引数チェック
1723    if (name == NULL)
1724    {
1725        return;
1726    }
1727
1728    // EXE ファイル名を取得
1729    GetModuleFileName(NULL, exe_path, sizeof(exe_path));
1730
1731    // ディレクトリ名を取得
1732    Win32GetDirFromPath(exe_dir, sizeof(exe_dir), exe_path);
1733
1734    StrCpy(name, size, exe_dir);
1735}
1736
1737// 終端の \ を抜く
1738void Win32NukuEnW(wchar_t *dst, UINT size, wchar_t *src)
1739{
1740    wchar_t str[MAX_SIZE];
1741    int i;
1742    if (src)
1743    {
1744        UniStrCpy(str, sizeof(str), src);
1745    }
1746    else
1747    {
1748        UniStrCpy(str, sizeof(str), dst);
1749    }
1750    i = UniStrLen(str);
1751    if (str[i - 1] == L'\\')
1752    {
1753        str[i - 1] = 0;
1754    }
1755    UniStrCpy(dst, size, str);
1756}
1757void Win32NukuEn(char *dst, UINT size, char *src)
1758{
1759    char str[MAX_SIZE];
1760    int i;
1761    if (src)
1762    {
1763        StrCpy(str, sizeof(str), src);
1764    }
1765    else
1766    {
1767        StrCpy(str, sizeof(str), dst);
1768    }
1769    i = StrLen(str);
1770    if (str[i - 1] == '\\')
1771    {
1772        str[i - 1] = 0;
1773    }
1774    StrCpy(dst, size, str);
1775}
1776
1777// ディレクトリ名をパスから取得
1778void Win32GetDirFromPathW(wchar_t *dst, UINT size, wchar_t *src)
1779{
1780    wchar_t str[MAX_SIZE];
1781    int i,len;
1782    wchar_t c;
1783    wchar_t tmp[MAX_SIZE];
1784    int wp;
1785    if (src)
1786    {
1787        UniStrCpy(str, sizeof(str), src);
1788    }
1789    else
1790    {
1791        UniStrCpy(str, sizeof(str), dst);
1792    }
1793    Win32NukuEnW(str, sizeof(str), NULL);
1794    wp = 0;
1795    len = UniStrLen(str);
1796    dst[0] = 0;
1797    for (i = 0;i < len;i++)
1798    {
1799        c = str[i];
1800        switch (c)
1801        {
1802        case L'\\':
1803            tmp[wp] = 0;
1804            wp = 0;
1805            UniStrCat(dst, size, tmp);
1806            UniStrCat(dst, size, L"\\");
1807            break;
1808        default:
1809            tmp[wp] = c;
1810            wp++;
1811            break;
1812        }
1813    }
1814    Win32NukuEnW(dst, size, NULL);
1815}
1816void Win32GetDirFromPath(char *dst, UINT size, char *src)
1817{
1818    char str[MAX_SIZE];
1819    int i,len;
1820    char c;
1821    char tmp[MAX_SIZE];
1822    int wp;
1823    if (src)
1824    {
1825        StrCpy(str, sizeof(str), src);
1826    }
1827    else
1828    {
1829        StrCpy(str, sizeof(str), dst);
1830    }
1831    Win32NukuEn(str, sizeof(str), NULL);
1832    wp = 0;
1833    len = StrLen(str);
1834    dst[0] = 0;
1835    for (i = 0;i < len;i++)
1836    {
1837        c = str[i];
1838        switch (c)
1839        {
1840        case '\\':
1841            tmp[wp] = 0;
1842            wp = 0;
1843            StrCat(dst, size, tmp);
1844            StrCat(dst, size, "\\");
1845            break;
1846        default:
1847            tmp[wp] = c;
1848            wp++;
1849            break;
1850        }
1851    }
1852    Win32NukuEn(dst, size, NULL);
1853}
1854
1855// ディレクトリの削除
1856bool Win32DeleteDirW(wchar_t *name)
1857{
1858    // 引数チェック
1859    if (name == NULL)
1860    {
1861        return false;
1862    }
1863
1864    if (IsNt() == false)
1865    {
1866        char *name_a = CopyUniToStr(name);
1867        bool ret = Win32DeleteDir(name_a);
1868
1869        Free(name_a);
1870
1871        return ret;
1872    }
1873
1874    if (RemoveDirectoryW(name) == FALSE)
1875    {
1876        return false;
1877    }
1878    return true;
1879}
1880bool Win32DeleteDir(char *name)
1881{
1882    // 引数チェック
1883    if (name == NULL)
1884    {
1885        return false;
1886    }
1887
1888    if (RemoveDirectory(name) == FALSE)
1889    {
1890        return false;
1891    }
1892    return true;
1893}
1894
1895// ディレクトリの作成
1896bool Win32MakeDirW(wchar_t *name)
1897{
1898    // 引数チェック
1899    if (name == NULL)
1900    {
1901        return false;
1902    }
1903
1904    if (IsNt() == false)
1905    {
1906        char *name_a = CopyUniToStr(name);
1907        bool ret = Win32MakeDir(name_a);
1908
1909        Free(name_a);
1910
1911        return ret;
1912    }
1913
1914    if (CreateDirectoryW(name, NULL) == FALSE)
1915    {
1916        return false;
1917    }
1918
1919    return true;
1920}
1921bool Win32MakeDir(char *name)
1922{
1923    // 引数チェック
1924    if (name == NULL)
1925    {
1926        return false;
1927    }
1928
1929    if (CreateDirectory(name, NULL) == FALSE)
1930    {
1931        return false;
1932    }
1933
1934    return true;
1935}
1936
1937// ファイルの削除
1938bool Win32FileDeleteW(wchar_t *name)
1939{
1940    // 引数チェック
1941    if (name == NULL)
1942    {
1943        return false;
1944    }
1945
1946    if (IsNt() == false)
1947    {
1948        bool ret;
1949        char *name_a = CopyUniToStr(name);
1950
1951        ret = Win32FileDelete(name_a);
1952
1953        Free(name_a);
1954
1955        return ret;
1956    }
1957
1958    if (DeleteFileW(name) == FALSE)
1959    {
1960        return false;
1961    }
1962    return true;
1963}
1964bool Win32FileDelete(char *name)
1965{
1966    // 引数チェック
1967    if (name == NULL)
1968    {
1969        return false;
1970    }
1971
1972    if (DeleteFile(name) == FALSE)
1973    {
1974        return false;
1975    }
1976    return true;
1977}
1978
1979// ファイルのシーク
1980bool Win32FileSeek(void *pData, UINT mode, int offset)
1981{
1982    WIN32IO *p;
1983    DWORD ret;
1984    // 引数チェック
1985    if (pData == NULL)
1986    {
1987        return false;
1988    }
1989    if (mode != FILE_BEGIN && mode != FILE_END && mode != FILE_CURRENT)
1990    {
1991        return false;
1992    }
1993
1994    p = (WIN32IO *)pData;
1995    ret = SetFilePointer(p->hFile, (LONG)offset, NULL, mode);
1996    if (ret == INVALID_SET_FILE_POINTER || ret == ERROR_NEGATIVE_SEEK)
1997    {
1998        return false;
1999    }
2000    return true;
2001}
2002
2003// ファイルサイズの取得
2004UINT64 Win32FileSize(void *pData)
2005{
2006    WIN32IO *p;
2007    UINT64 ret;
2008    DWORD tmp;
2009    // 引数チェック
2010    if (pData == NULL)
2011    {
2012        return 0;
2013    }
2014
2015    p = (WIN32IO *)pData;
2016    tmp = 0;
2017    ret = GetFileSize(p->hFile, &tmp);
2018    if (ret == (DWORD)-1)
2019    {
2020        return 0;
2021    }
2022
2023    if (tmp != 0)
2024    {
2025        ret += (UINT64)tmp * 4294967296ULL;
2026    }
2027
2028    return ret;
2029}
2030
2031// ファイルに書き込む
2032bool Win32FileWrite(void *pData, void *buf, UINT size)
2033{
2034    WIN32IO *p;
2035    DWORD write_size;
2036    // 引数チェック
2037    if (pData == NULL || buf == NULL || size == 0)
2038    {
2039        return false;
2040    }
2041
2042    p = (WIN32IO *)pData;
2043    if (WriteFile(p->hFile, buf, size, &write_size, NULL) == FALSE)
2044    {
2045        return false;
2046    }
2047
2048    if (write_size != size)
2049    {
2050        return false;
2051    }
2052
2053    return true;
2054}
2055
2056// ファイルから読み込む
2057bool Win32FileRead(void *pData, void *buf, UINT size)
2058{
2059    WIN32IO *p;
2060    DWORD read_size;
2061    // 引数チェック
2062    if (pData == NULL || buf == NULL || size == 0)
2063    {
2064        return false;
2065    }
2066
2067    p = (WIN32IO *)pData;
2068    if (ReadFile(p->hFile, buf, size, &read_size, NULL) == FALSE)
2069    {
2070        return false;
2071    }
2072
2073    if (read_size != size)
2074    {
2075        return false;
2076    }
2077   
2078    return true;;
2079}
2080
2081// ファイルを閉じる
2082void Win32FileClose(void *pData, bool no_flush)
2083{
2084    WIN32IO *p;
2085    // 引数チェック
2086    if (pData == NULL)
2087    {
2088        return;
2089    }
2090
2091    p = (WIN32IO *)pData;
2092    if (p->WriteMode && no_flush == false)
2093    {
2094        FlushFileBuffers(p->hFile);
2095    }
2096    CloseHandle(p->hFile);
2097    p->hFile = NULL;
2098
2099    // メモリ解放
2100    Win32MemoryFree(p);
2101}
2102
2103// ファイルをフラッシュする
2104void Win32FileFlush(void *pData)
2105{
2106    WIN32IO *p;
2107    // 引数チェック
2108    if (pData == NULL)
2109    {
2110        return;
2111    }
2112
2113    p = (WIN32IO *)pData;
2114    if (p->WriteMode)
2115    {
2116        FlushFileBuffers(p->hFile);
2117    }
2118}
2119
2120// ファイルを開く
2121void *Win32FileOpenW(wchar_t *name, bool write_mode, bool read_lock)
2122{
2123    WIN32IO *p;
2124    HANDLE h;
2125    DWORD lock_mode;
2126    // 引数チェック
2127    if (name == NULL)
2128    {
2129        return NULL;
2130    }
2131
2132    if (IsNt() == false)
2133    {
2134        void *ret;
2135        char *name_a = CopyUniToStr(name);
2136
2137        ret = Win32FileOpen(name_a, write_mode, read_lock);
2138
2139        Free(name_a);
2140
2141        return ret;
2142    }
2143
2144    if (write_mode)
2145    {
2146        lock_mode = FILE_SHARE_READ;
2147    }
2148    else
2149    {
2150        if (read_lock == false)
2151        {
2152            lock_mode = FILE_SHARE_READ | FILE_SHARE_WRITE;
2153        }
2154        else
2155        {
2156            lock_mode = FILE_SHARE_READ;
2157        }
2158    }
2159
2160    // ファイルを開く
2161    h = CreateFileW(name,
2162        (write_mode ? GENERIC_READ | GENERIC_WRITE : GENERIC_READ),
2163        lock_mode,
2164        NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
2165    if (h == INVALID_HANDLE_VALUE)
2166    {
2167        UINT ret = GetLastError();
2168        // 失敗
2169        return NULL;
2170    }
2171
2172    // メモリ確保
2173    p = Win32MemoryAlloc(sizeof(WIN32IO));
2174    // ハンドル格納
2175    p->hFile = h;
2176
2177    p->WriteMode = write_mode;
2178
2179    return (void *)p;
2180}
2181void *Win32FileOpen(char *name, bool write_mode, bool read_lock)
2182{
2183    WIN32IO *p;
2184    HANDLE h;
2185    DWORD lock_mode;
2186    // 引数チェック
2187    if (name == NULL)
2188    {
2189        return NULL;
2190    }
2191
2192    if (write_mode)
2193    {
2194        lock_mode = FILE_SHARE_READ;
2195    }
2196    else
2197    {
2198        if (read_lock == false)
2199        {
2200            lock_mode = FILE_SHARE_READ | FILE_SHARE_WRITE;
2201        }
2202        else
2203        {
2204            lock_mode = FILE_SHARE_READ;
2205        }
2206    }
2207
2208    // ファイルを開く
2209    h = CreateFile(name,
2210        (write_mode ? GENERIC_READ | GENERIC_WRITE : GENERIC_READ),
2211        lock_mode,
2212        NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
2213    if (h == INVALID_HANDLE_VALUE)
2214    {
2215        UINT ret = GetLastError();
2216        // 失敗
2217        return NULL;
2218    }
2219
2220    // メモリ確保
2221    p = Win32MemoryAlloc(sizeof(WIN32IO));
2222    // ハンドル格納
2223    p->hFile = h;
2224
2225    p->WriteMode = write_mode;
2226
2227    return (void *)p;
2228}
2229
2230// ファイルを作成する
2231void *Win32FileCreateW(wchar_t *name)
2232{
2233    WIN32IO *p;
2234    HANDLE h;
2235    // 引数チェック
2236    if (name == NULL)
2237    {
2238        return NULL;
2239    }
2240
2241    if (IsNt() == false)
2242    {
2243        void *ret;
2244        char *name_a = CopyUniToStr(name);
2245
2246        ret = Win32FileCreate(name_a);
2247
2248        Free(name_a);
2249
2250        return ret;
2251    }
2252
2253    // ファイルを作成する
2254    h = CreateFileW(name, GENERIC_READ | GENERIC_WRITE,
2255        FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
2256        NULL);
2257    if (h == INVALID_HANDLE_VALUE)
2258    {
2259        h = CreateFileW(name, GENERIC_READ | GENERIC_WRITE,
2260            FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_HIDDEN,
2261            NULL);
2262        if (h == INVALID_HANDLE_VALUE)
2263        {
2264            return NULL;
2265        }
2266    }
2267
2268    // メモリ確保
2269    p = Win32MemoryAlloc(sizeof(WIN32IO));
2270    // ハンドル格納
2271    p->hFile = h;
2272
2273    p->WriteMode = true;
2274
2275    return (void *)p;
2276}
2277void *Win32FileCreate(char *name)
2278{
2279    WIN32IO *p;
2280    HANDLE h;
2281    // 引数チェック
2282    if (name == NULL)
2283    {
2284        return NULL;
2285    }
2286
2287    // ファイルを作成する
2288    h = CreateFile(name, GENERIC_READ | GENERIC_WRITE,
2289        FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
2290        NULL);
2291    if (h == INVALID_HANDLE_VALUE)
2292    {
2293        h = CreateFile(name, GENERIC_READ | GENERIC_WRITE,
2294            FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_HIDDEN,
2295            NULL);
2296        if (h == INVALID_HANDLE_VALUE)
2297        {
2298            return NULL;
2299        }
2300    }
2301
2302    // メモリ確保
2303    p = Win32MemoryAlloc(sizeof(WIN32IO));
2304    // ハンドル格納
2305    p->hFile = h;
2306
2307    p->WriteMode = true;
2308
2309    return (void *)p;
2310}
2311
2312#define SIZE_OF_CALLSTACK_SYM   10000
2313#define CALLSTACK_DEPTH         12
2314
2315// コールスタックの取得
2316CALLSTACK_DATA *Win32GetCallStack()
2317{
2318#ifndef WIN32_NO_DEBUG_HELP_DLL
2319    DWORD current_eip32 = 0, current_esp32 = 0, current_ebp32 = 0;
2320    UINT64 current_eip = 0, current_esp = 0, current_ebp = 0;
2321    STACKFRAME64 sf;
2322    CALLSTACK_DATA *cs = NULL, *s;
2323
2324#ifdef  CPU_64
2325    CONTEXT context;
2326#endif  // CPU_64
2327
2328    bool ret;
2329    UINT depth = 0;
2330
2331#ifndef CPU_64
2332    // レジスタ取得 (32 bit)
2333    __asm
2334    {
2335        mov current_esp32, esp
2336        mov current_ebp32, ebp
2337    };
2338
2339    current_eip32 = (DWORD)Win32GetCallStack;
2340
2341    current_eip = (UINT64)current_eip32;
2342    current_esp = (UINT64)current_esp32;
2343    current_ebp = (UINT64)current_ebp32;
2344#else   // CPU_64
2345    // レジスタ取得 (64 bit)
2346    Zero(&context, sizeof(context));
2347    context.ContextFlags = CONTEXT_FULL;
2348    RtlCaptureContext(&context);
2349#endif  // CPU_64
2350
2351    Zero(&sf, sizeof(sf));
2352
2353#ifndef CPU_64
2354    sf.AddrPC.Offset = current_eip;
2355    sf.AddrStack.Offset = current_esp;
2356    sf.AddrFrame.Offset = current_ebp;
2357#else   // CPU_64
2358    sf.AddrPC.Offset = context.Rip;
2359    sf.AddrStack.Offset = context.Rsp;
2360    sf.AddrFrame.Offset = context.Rsp;
2361#endif  // CPU_64
2362
2363    sf.AddrPC.Mode = AddrModeFlat;
2364    sf.AddrStack.Mode = AddrModeFlat;
2365    sf.AddrFrame.Mode = AddrModeFlat;
2366
2367    while (true)
2368    {
2369        DWORD type = IMAGE_FILE_MACHINE_I386;
2370
2371#ifdef  CPU_64
2372        type = IMAGE_FILE_MACHINE_AMD64;
2373#endif  // CPU_64
2374
2375        if ((depth++) >= CALLSTACK_DEPTH)
2376        {
2377            break;
2378        }
2379
2380#ifndef CPU_64
2381        ret = StackWalk64(type,
2382            hCurrentProcessHandle,
2383            GetCurrentThread(),
2384            &sf,
2385            NULL, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL);
2386#else   // CPU_64
2387        ret = StackWalk64(type,
2388            hCurrentProcessHandle,
2389            GetCurrentThread(),
2390            &sf,
2391            &context, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL);
2392#endif  // CPU_64
2393        if (ret == false || sf.AddrFrame.Offset == 0)
2394        {
2395            break;
2396        }
2397
2398        if (cs == NULL)
2399        {
2400            cs = OSMemoryAlloc(sizeof(CALLSTACK_DATA));
2401            s = cs;
2402        }
2403        else
2404        {
2405            s->next = OSMemoryAlloc(sizeof(CALLSTACK_DATA));
2406            s = s->next;
2407        }
2408        s->symbol_cache = false;
2409        s->next = NULL;
2410        s->offset = sf.AddrPC.Offset;
2411        s->disp = 0;
2412        s->name = NULL;
2413        s->line = 0;
2414        s->filename[0] = 0;
2415    }
2416
2417    return cs;
2418#else   // WIN32_NO_DEBUG_HELP_DLL
2419    return NULL;
2420#endif  // WIN32_NO_DEBUG_HELP_DLL
2421}
2422
2423// コールスタックからシンボル情報を取得
2424bool Win32GetCallStackSymbolInfo(CALLSTACK_DATA *s)
2425{
2426#ifdef  WIN32_NO_DEBUG_HELP_DLL
2427    return false;
2428#else   // WIN32_NO_DEBUG_HELP_DLL
2429    UINT64 disp;
2430    UINT disp32, len;
2431    IMAGEHLP_SYMBOL64 *sym;
2432    IMAGEHLP_LINE64 line;
2433    char tmp[MAX_PATH];
2434    // 引数チェック
2435    if (s == NULL)
2436    {
2437        return false;
2438    }
2439
2440    if (s->symbol_cache)
2441    {
2442        return true;
2443    }
2444
2445    sym = OSMemoryAlloc(SIZE_OF_CALLSTACK_SYM);
2446    sym->SizeOfStruct = SIZE_OF_CALLSTACK_SYM;
2447    sym->MaxNameLength = SIZE_OF_CALLSTACK_SYM - sizeof(IMAGEHLP_SYMBOL64);
2448
2449    if (SymGetSymFromAddr64(hCurrentProcessHandle, s->offset, &disp, sym))
2450    {
2451        s->disp = disp;
2452        s->name = OSMemoryAlloc((UINT)strlen(sym->Name) + 1);
2453        lstrcpy(s->name, sym->Name);
2454    }
2455    else
2456    {
2457        s->disp = 0;
2458        s->name = NULL;
2459    }
2460
2461    Zero(&line, sizeof(line));
2462    line.SizeOfStruct = sizeof(line);
2463    if (SymGetLineFromAddr64(hCurrentProcessHandle, s->offset, &disp32, &line))
2464    {
2465        disp = (UINT64)disp32;
2466        s->line = line.LineNumber;
2467        lstrcpy(s->filename, line.FileName);
2468        Win32GetDirFromPath(tmp, sizeof(tmp), s->filename);
2469        len = lstrlen(tmp);
2470        lstrcpy(tmp, &s->filename[len + 1]);
2471        lstrcpy(s->filename, tmp);
2472    }
2473    else
2474    {
2475        s->line = 0;
2476        s->filename[0] = 0;
2477    }
2478
2479    OSMemoryFree(sym);
2480
2481    s->symbol_cache = true;
2482
2483    return true;
2484#endif  // WIN32_NO_DEBUG_HELP_DLL
2485}
2486
2487// デフォルトの Win32 スレッド
2488DWORD CALLBACK Win32DefaultThreadProc(void *param)
2489{
2490    WIN32THREADSTARTUPINFO *info = (WIN32THREADSTARTUPINFO *)param;
2491    // 引数チェック
2492    if (info == NULL)
2493    {
2494        return 0;
2495    }
2496
2497    Win32InitNewThread();
2498
2499    // スレッド関数の呼び出し
2500    info->thread_proc(info->thread, info->param);
2501
2502    // 参照の解放
2503    ReleaseThread(info->thread);
2504
2505    Win32MemoryFree(info);
2506
2507    FreeOpenSSLThreadState();
2508
2509    _endthreadex(0);
2510    return 0;
2511}
2512
2513// スレッドの終了を待機
2514bool Win32WaitThread(THREAD *t)
2515{
2516    WIN32THREAD *w;
2517    // 引数チェック
2518    if (t == NULL)
2519    {
2520        return false;
2521    }
2522    w = (WIN32THREAD *)t->pData;
2523    if (w == NULL)
2524    {
2525        return false;
2526    }
2527
2528    // スレッドイベントを待機する
2529    if (WaitForSingleObject(w->hThread, INFINITE) == WAIT_OBJECT_0)
2530    {
2531        // スレッドがシグナル状態になった
2532        return true;
2533    }
2534
2535    // 待機失敗 (タイムアウト等)
2536    return false;
2537}
2538
2539// スレッドの解放
2540void Win32FreeThread(THREAD *t)
2541{
2542    WIN32THREAD *w;
2543    // 引数チェック
2544    if (t == NULL)
2545    {
2546        return;
2547    }
2548    w = (WIN32THREAD *)t->pData;
2549    if (w == NULL)
2550    {
2551        return;
2552    }
2553
2554    // ハンドルを閉じる
2555    CloseHandle(w->hThread);
2556
2557    // メモリ解放
2558    Win32MemoryFree(t->pData);
2559    t->pData = NULL;
2560}
2561
2562// スレッドの初期化
2563bool Win32InitThread(THREAD *t)
2564{
2565    WIN32THREAD *w;
2566    HANDLE hThread;
2567    DWORD thread_id;
2568    WIN32THREADSTARTUPINFO *info;
2569    // 引数チェック
2570    if (t == NULL)
2571    {
2572        return false;
2573    }
2574    if (t->thread_proc == NULL)
2575    {
2576        return false;
2577    }
2578
2579    // スレッドデータ生成
2580    w = Win32MemoryAlloc(sizeof(WIN32THREAD));
2581
2582    // 起動情報生成
2583    info = Win32MemoryAlloc(sizeof(WIN32THREADSTARTUPINFO));
2584    info->param = t->param;
2585    info->thread_proc = t->thread_proc;
2586    info->thread = t;
2587    AddRef(t->ref);
2588
2589    // スレッド作成
2590    t->pData = w;
2591    hThread = (HANDLE)_beginthreadex(NULL, 0, Win32DefaultThreadProc, info, 0, &thread_id);
2592    if (hThread == NULL)
2593    {
2594        // スレッド作成失敗
2595        t->pData = NULL;
2596        Release(t->ref);
2597        Win32MemoryFree(info);
2598        Win32MemoryFree(w);
2599        return false;
2600    }
2601
2602    // スレッド情報の保存
2603    w->hThread = hThread;
2604    w->thread_id = thread_id;
2605
2606    return true;
2607}
2608
2609// Win32 用ライブラリの初期化
2610void Win32Init()
2611{
2612    INITCOMMONCONTROLSEX c;
2613    OSVERSIONINFO os;
2614
2615    // Windows NT かどうか取得する
2616    Zero(&os, sizeof(os));
2617    os.dwOSVersionInfoSize = sizeof(os);
2618    GetVersionEx(&os);
2619
2620    if (os.dwPlatformId == VER_PLATFORM_WIN32_NT)
2621    {
2622        // NT 系
2623        win32_is_nt = true;
2624    }
2625    else
2626    {
2627        // 9x 系
2628        win32_is_nt = false;
2629    }
2630
2631    // stdout を開く
2632    if (hstdout == INVALID_HANDLE_VALUE)
2633    {
2634        hstdout = GetStdHandle(STD_OUTPUT_HANDLE);
2635    }
2636
2637    // stdin を開く
2638    if (hstdin == INVALID_HANDLE_VALUE)
2639    {
2640        hstdin = GetStdHandle(STD_INPUT_HANDLE);
2641    }
2642
2643    Win32InitNewThread();
2644
2645    CoInitialize(NULL);
2646
2647    InitializeCriticalSection(&fasttick_lock);
2648
2649#ifdef  WIN32_USE_HEAP_API_FOR_MEMORY
2650    use_heap_api = true;
2651#else   // WIN32_USE_HEAP_API_FOR_MEMORY
2652    use_heap_api = false;
2653#endif  // WIN32_USE_HEAP_API_FOR_MEMORY
2654
2655    if (MayaquaIsDotNetMode())
2656    {
2657        // .NET API 内からヒープ関係の API を呼び出すとクラッシュする
2658        use_heap_api = false;
2659    }
2660
2661    if (IsNt() == false)
2662    {
2663        // Win9x ではヒープ関係の API は使用しない
2664        use_heap_api = false;
2665    }
2666
2667    if (use_heap_api)
2668    {
2669        heap_handle = HeapCreate(0, 0, 0);
2670    }
2671
2672    // プロセス擬似ハンドルの取得
2673    hCurrentProcessHandle = GetCurrentProcess();
2674
2675    // カレントディレクトリの初期化
2676    // Win32InitCurrentDir(); /* 行わない */
2677
2678    // シンボルハンドラの初期化
2679    if (IsMemCheck())
2680    {
2681#ifndef WIN32_NO_DEBUG_HELP_DLL
2682        SymInitialize(hCurrentProcessHandle, NULL, TRUE);
2683#endif  // WIN32_NO_DEBUG_HELP_DLL
2684    }
2685
2686    // Common Control の初期化
2687    Zero(&c, sizeof(INITCOMMONCONTROLSEX));
2688    c.dwSize = sizeof(INITCOMMONCONTROLSEX);
2689    c.dwICC = ICC_ANIMATE_CLASS | ICC_BAR_CLASSES | ICC_COOL_CLASSES |
2690        ICC_DATE_CLASSES | ICC_HOTKEY_CLASS | ICC_INTERNET_CLASSES |
2691        ICC_LISTVIEW_CLASSES | ICC_NATIVEFNTCTL_CLASS |
2692        ICC_PAGESCROLLER_CLASS | ICC_PROGRESS_CLASS |
2693        ICC_TAB_CLASSES | ICC_TREEVIEW_CLASSES | ICC_UPDOWN_CLASS | ICC_USEREX_CLASSES |
2694        ICC_WIN95_CLASSES;
2695    InitCommonControlsEx(&c);
2696}
2697
2698// Win32 用ライブラリの解放
2699void Win32Free()
2700{
2701    // シンボルハンドラを閉じる
2702    if (IsMemCheck())
2703    {
2704#ifndef WIN32_NO_DEBUG_HELP_DLL
2705        SymCleanup(hCurrentProcessHandle);
2706#endif  // WIN32_NO_DEBUG_HELP_DLL
2707    }
2708
2709    if (use_heap_api)
2710    {
2711        HeapDestroy(heap_handle);
2712        heap_handle = NULL;
2713    }
2714
2715    CoUninitialize();
2716
2717    DeleteCriticalSection(&fasttick_lock);
2718}
2719
2720// メモリ確保
2721void *Win32MemoryAlloc(UINT size)
2722{
2723    if (use_heap_api)
2724    {
2725        return HeapAlloc(heap_handle, 0, size);
2726    }
2727    else
2728    {
2729        return malloc(size);
2730    }
2731}
2732
2733// メモリ再確保
2734void *Win32MemoryReAlloc(void *addr, UINT size)
2735{
2736    if (use_heap_api)
2737    {
2738        return HeapReAlloc(heap_handle, 0, addr, size);
2739    }
2740    else
2741    {
2742        return realloc(addr, size);
2743    }
2744}
2745
2746// メモリ確報
2747void Win32MemoryFree(void *addr)
2748{
2749    if (use_heap_api)
2750    {
2751        HeapFree(heap_handle, 0, addr);
2752    }
2753    else
2754    {
2755        free(addr);
2756    }
2757}
2758
2759// システムタイマの取得
2760UINT Win32GetTick()
2761{
2762    return (UINT)timeGetTime();
2763}
2764
2765// システム時刻の取得
2766void Win32GetSystemTime(SYSTEMTIME *system_time)
2767{
2768    // システム時刻の取得
2769    GetSystemTime(system_time);
2770}
2771
2772// 32bit 整数のインクリメント
2773void Win32Inc32(UINT *value)
2774{
2775    InterlockedIncrement(value);
2776}
2777
2778// 32bit 整数のデクリメント
2779void Win32Dec32(UINT *value)
2780{
2781    InterlockedDecrement(value);
2782}
2783
2784// スレッドの休止
2785void Win32Sleep(UINT time)
2786{
2787    Sleep(time);
2788}
2789
2790// ロックの作成
2791LOCK *Win32NewLock()
2792{
2793    // メモリ確保
2794    LOCK *lock = Win32MemoryAlloc(sizeof(LOCK));
2795
2796    // クリティカルセクション確保
2797    CRITICAL_SECTION *critical_section = Win32MemoryAlloc(sizeof(CRITICAL_SECTION));
2798
2799    if (lock == NULL || critical_section == NULL)
2800    {
2801        Win32MemoryFree(lock);
2802        Win32MemoryFree(critical_section);
2803        return NULL;
2804    }
2805
2806    // クリティカルセクション初期化
2807    InitializeCriticalSection(critical_section);
2808
2809    lock->pData = (void *)critical_section;
2810    lock->Ready = true;
2811
2812    return lock;
2813}
2814
2815// ロック
2816bool Win32Lock(LOCK *lock)
2817{
2818    CRITICAL_SECTION *critical_section;
2819    if (lock->Ready == false)
2820    {
2821        // 状態が不正
2822        return false;
2823    }
2824
2825    // クリティカルセクションに入る
2826    critical_section = (CRITICAL_SECTION *)lock->pData;
2827    EnterCriticalSection(critical_section);
2828
2829    return true;
2830}
2831
2832// ロック解除
2833void Win32Unlock(LOCK *lock)
2834{
2835    Win32UnlockEx(lock, false);
2836}
2837void Win32UnlockEx(LOCK *lock, bool inner)
2838{
2839    CRITICAL_SECTION *critical_section;
2840    if (lock->Ready == false && inner == false)
2841    {
2842        // 状態が不正
2843        return;
2844    }
2845
2846    // クリティカルセクションから出る
2847    critical_section = (CRITICAL_SECTION *)lock->pData;
2848    LeaveCriticalSection(critical_section);
2849}
2850
2851// ロックの削除
2852void Win32DeleteLock(LOCK *lock)
2853{
2854    CRITICAL_SECTION *critical_section;
2855    // Ready フラグを安全に解除する
2856    Win32Lock(lock);
2857    lock->Ready = false;
2858    Win32UnlockEx(lock, true);
2859
2860    // クリティカルセクションの削除
2861    critical_section = (CRITICAL_SECTION *)lock->pData;
2862    DeleteCriticalSection(critical_section);
2863
2864    // メモリ解放
2865    Win32MemoryFree(critical_section);
2866    Win32MemoryFree(lock);
2867}
2868
2869// イベントの初期化
2870void Win32InitEvent(EVENT *event)
2871{
2872    // 自動リセットイベントの作成
2873    HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
2874
2875    event->pData = hEvent;
2876}
2877
2878// イベントのセット
2879void Win32SetEvent(EVENT *event)
2880{
2881    HANDLE hEvent = (HANDLE)event->pData;
2882    if (hEvent == NULL)
2883    {
2884        return;
2885    }
2886
2887    SetEvent(hEvent);
2888}
2889
2890// イベントのリセット
2891void Win32ResetEvent(EVENT *event)
2892{
2893    HANDLE hEvent = (HANDLE)event->pData;
2894    if (hEvent == NULL)
2895    {
2896        return;
2897    }
2898
2899    ResetEvent(hEvent);
2900}
2901
2902// イベントを待機する
2903bool Win32WaitEvent(EVENT *event, UINT timeout)
2904{
2905    HANDLE hEvent = (HANDLE)event->pData;
2906    UINT ret;
2907    if (hEvent == NULL)
2908    {
2909        return false;
2910    }
2911
2912    // オブジェクトを待機
2913    ret = WaitForSingleObject(hEvent, timeout);
2914    if (ret == WAIT_TIMEOUT)
2915    {
2916        // タイムアウト
2917        return false;
2918    }
2919    else
2920    {
2921        // シグナル状態
2922        return true;
2923    }
2924}
2925
2926// イベントの解放
2927void Win32FreeEvent(EVENT *event)
2928{
2929    HANDLE hEvent = (HANDLE)event->pData;
2930    if (hEvent == NULL)
2931    {
2932        return;
2933    }
2934
2935    CloseHandle(hEvent);
2936}
2937
2938// Win32 専用の高速な 64 bit Tick 取得関数
2939UINT64 Win32FastTick64()
2940{
2941    static UINT last_tick = 0;
2942    static UINT counter = 0;
2943    UINT64 ret;
2944    UINT tick;
2945
2946    EnterCriticalSection(&fasttick_lock);
2947
2948    // 現在の tick 値を取得する
2949    tick = Win32GetTick();
2950
2951    if (last_tick > tick)
2952    {
2953        // 前回取得した tick 値のほうが今回取得した値よりも大きい場合
2954        // カウンタが 1 回りしたと考えることができる
2955
2956        counter++;
2957    }
2958
2959    last_tick = tick;
2960
2961    ret = (UINT64)tick + (UINT64)counter * 4294967296ULL;
2962
2963    LeaveCriticalSection(&fasttick_lock);
2964
2965    if (start_tick == 0)
2966    {
2967        start_tick = ret;
2968        ret = 0;
2969    }
2970    else
2971    {
2972        ret -= start_tick;
2973    }
2974
2975    return ret + 1;
2976}
2977
2978// 文字列をコンソールから読み込む
2979bool Win32InputW(wchar_t *str, UINT size)
2980{
2981    bool ret = false;
2982    // 引数チェック
2983    if (str == NULL)
2984    {
2985        return false;
2986    }
2987    if (size == 0)
2988    {
2989        size = 0x7fffffff;
2990    }
2991
2992    if (str == NULL || size <= sizeof(wchar_t))
2993    {
2994        if (str != NULL)
2995        {
2996            Zero(str, size);
2997        }
2998
2999        return Win32InputFromFileW(NULL, 0);
3000    }
3001
3002    if (IsNt())
3003    {
3004        DWORD read_size = 0;
3005
3006        if (ReadConsoleW(hstdin, str, (size - sizeof(wchar_t)), &read_size, NULL))
3007        {
3008            str[read_size] = 0;
3009
3010            UniTrimCrlf(str);
3011
3012            ret = true;
3013        }
3014        else
3015        {
3016            ret = Win32InputFromFileW(str, size);
3017        }
3018    }
3019    else
3020    {
3021        DWORD read_size = 0;
3022        UINT a_size = size / sizeof(wchar_t) + 16;
3023        char *a;
3024
3025        a = ZeroMalloc(a_size);
3026
3027        if (ReadConsoleA(hstdin, a, a_size - 1, &read_size, NULL))
3028        {
3029            a[read_size] = 0;
3030
3031            StrToUni(str, size, a);
3032
3033            UniTrimCrlf(str);
3034
3035            ret = true;
3036        }
3037        else
3038        {
3039            ret = Win32InputFromFileW(str, size);
3040        }
3041
3042        Free(a);
3043    }
3044
3045    return ret;
3046}
3047// 1 行を標準入力から取得
3048bool Win32InputFromFileW(wchar_t *str, UINT size)
3049{
3050    char *a;
3051    if (str == NULL)
3052    {
3053        wchar_t tmp[MAX_SIZE];
3054        Win32InputFromFileW(tmp, sizeof(tmp));
3055        return false;
3056    }
3057
3058    a = Win32InputFromFileLineA();
3059    if (a == NULL)
3060    {
3061        UniStrCpy(str, size, L"");
3062        return false;
3063    }
3064
3065    UtfToUni(str, size, a);
3066
3067    UniTrimCrlf(str);
3068
3069    Free(a);
3070
3071    return true;
3072}
3073char *Win32InputFromFileLineA()
3074{
3075    BUF *b = NewBuf();
3076    char zero = 0;
3077    char *ret = NULL;
3078    bool ok = true;
3079
3080    while (true)
3081    {
3082        char c;
3083        UINT read_size = 0;
3084
3085        if (ReadFile(hstdin, &c, 1, &read_size, NULL) == false)
3086        {
3087            ok = false;
3088            break;
3089        }
3090        if (read_size != 1)
3091        {
3092            ok = false;
3093            break;
3094        }
3095
3096        WriteBuf(b, &c, 1);
3097
3098        if (c == 10)
3099        {
3100            break;
3101        }
3102    }
3103
3104    WriteBuf(b, &zero, 1);
3105
3106    if (ok)
3107    {
3108        ret = CopyStr(b->Buf);
3109    }
3110
3111    FreeBuf(b);
3112
3113    return ret;
3114}
3115
3116// 文字列をコンソールにプリントする
3117void Win32PrintW(wchar_t *str)
3118{
3119    DWORD write_size = 0;
3120    // 引数チェック
3121    if (str == NULL)
3122    {
3123        return;
3124    }
3125
3126    if (IsNt())
3127    {
3128        if (WriteConsoleW(hstdout, str, UniStrLen(str), &write_size, NULL) == false)
3129        {
3130            Win32PrintToFileW(str);
3131        }
3132    }
3133    else
3134    {
3135        char *ansi_str = CopyUniToStr(str);
3136
3137        if (WriteConsoleA(hstdout, ansi_str, StrLen(ansi_str), &write_size, NULL) == false)
3138        {
3139            Win32PrintToFileW(str);
3140        }
3141
3142        Free(ansi_str);
3143    }
3144}
3145void Win32PrintToFileW(wchar_t *str)
3146{
3147    char *utf;
3148    DWORD size = 0;
3149    // 引数チェック
3150    if (str == NULL)
3151    {
3152        return;
3153    }
3154
3155    utf = CopyUniToUtf(str);
3156
3157    WriteFile(hstdout, utf, StrLen(utf), &size, NULL);
3158
3159    Free(utf);
3160}
3161
3162
3163#endif  // WIN32
3164
3165
Note: See TracBrowser for help on using the repository browser.