#!/usr/bin/env python3

import argparse
import os
import platform
import subprocess

"""
refer to https://docs.microsoft.com/en-us/cpp/build/configuring-programs-for-windows-xp?view=msvc-160
xp sp2(x86) do not support vc runtime fully, casused by KERNEL32.dll do not implement some base apis
for c++ std function, for example, std::mutex/std::thread, we do not want create a real xp sp2 env or
create a wine xp sp2 env to test load_and_run, as a workround, we test target pe file import functions
are in KERNEL32.dll export function lists or not!
"""

# cmd.exe /c "dumpbin /exports KERNEL32.dll"
# KERNEL32.dll from Windows xp sp2 2002 C:\WINDOWS\system32
# please do not modify KERNEL32_XP_SP2_EXPORT_SYMBOLS when your MR failed
KERNEL32_XP_SP2_EXPORT_SYMBOLS = [
    "ActivateActCtx",
    "AddAtomA",
    "AddAtomW",
    "AddConsoleAliasA",
    "AddConsoleAliasW",
    "AddLocalAlternateComputerNameA",
    "AddLocalAlternateComputerNameW",
    "AddRefActCtx",
    "AddVectoredExceptionHandler",
    "AllocConsole",
    "AllocateUserPhysicalPages",
    "AreFileApisANSI",
    "AssignProcessToJobObject",
    "AttachConsole",
    "BackupRead",
    "BackupSeek",
    "BackupWrite",
    "BaseCheckAppcompatCache",
    "BaseCleanupAppcompatCache",
    "BaseCleanupAppcompatCacheSupport",
    "BaseDumpAppcompatCache",
    "BaseFlushAppcompatCache",
    "BaseInitAppcompatCache",
    "BaseInitAppcompatCacheSupport",
    "BaseProcessInitPostImport",
    "BaseQueryModuleData",
    "BaseUpdateAppcompatCache",
    "BasepCheckWinSaferRestrictions",
    "Beep",
    "BeginUpdateResourceA",
    "BeginUpdateResourceW",
    "BindIoCompletionCallback",
    "BuildCommDCBA",
    "BuildCommDCBAndTimeoutsA",
    "BuildCommDCBAndTimeoutsW",
    "BuildCommDCBW",
    "CallNamedPipeA",
    "CallNamedPipeW",
    "CancelDeviceWakeupRequest",
    "CancelIo",
    "CancelTimerQueueTimer",
    "CancelWaitableTimer",
    "ChangeTimerQueueTimer",
    "CheckNameLegalDOS8Dot3A",
    "CheckNameLegalDOS8Dot3W",
    "CheckRemoteDebuggerPresent",
    "ClearCommBreak",
    "ClearCommError",
    "CloseConsoleHandle",
    "CloseHandle",
    "CloseProfileUserMapping",
    "CmdBatNotification",
    "CommConfigDialogA",
    "CommConfigDialogW",
    "CompareFileTime",
    "CompareStringA",
    "CompareStringW",
    "ConnectNamedPipe",
    "ConsoleMenuControl",
    "ContinueDebugEvent",
    "ConvertDefaultLocale",
    "ConvertFiberToThread",
    "ConvertThreadToFiber",
    "CopyFileA",
    "CopyFileExA",
    "CopyFileExW",
    "CopyFileW",
    "CopyLZFile",
    "CreateActCtxA",
    "CreateActCtxW",
    "CreateConsoleScreenBuffer",
    "CreateDirectoryA",
    "CreateDirectoryExA",
    "CreateDirectoryExW",
    "CreateDirectoryW",
    "CreateEventA",
    "CreateEventW",
    "CreateFiber",
    "CreateFiberEx",
    "CreateFileA",
    "CreateFileMappingA",
    "CreateFileMappingW",
    "CreateFileW",
    "CreateHardLinkA",
    "CreateHardLinkW",
    "CreateIoCompletionPort",
    "CreateJobObjectA",
    "CreateJobObjectW",
    "CreateJobSet",
    "CreateMailslotA",
    "CreateMailslotW",
    "CreateMemoryResourceNotification",
    "CreateMutexA",
    "CreateMutexW",
    "CreateNamedPipeA",
    "CreateNamedPipeW",
    "CreateNlsSecurityDescriptor",
    "CreatePipe",
    "CreateProcessA",
    "CreateProcessInternalA",
    "CreateProcessInternalW",
    "CreateProcessInternalWSecure",
    "CreateProcessW",
    "CreateRemoteThread",
    "CreateSemaphoreA",
    "CreateSemaphoreW",
    "CreateSocketHandle",
    "CreateTapePartition",
    "CreateThread",
    "CreateTimerQueue",
    "CreateTimerQueueTimer",
    "CreateToolhelp32Snapshot",
    "CreateVirtualBuffer",
    "CreateWaitableTimerA",
    "CreateWaitableTimerW",
    "DeactivateActCtx",
    "DebugActiveProcess",
    "DebugActiveProcessStop",
    "DebugBreak",
    "DebugBreakProcess",
    "DebugSetProcessKillOnExit",
    "DecodePointer",
    "DecodeSystemPointer",
    "DefineDosDeviceA",
    "DefineDosDeviceW",
    "DelayLoadFailureHook",
    "DeleteAtom",
    "DeleteCriticalSection",
    "DeleteFiber",
    "DeleteFileA",
    "DeleteFileW",
    "DeleteTimerQueue",
    "DeleteTimerQueueEx",
    "DeleteTimerQueueTimer",
    "DeleteVolumeMountPointA",
    "DeleteVolumeMountPointW",
    "DeviceIoControl",
    "DisableThreadLibraryCalls",
    "DisconnectNamedPipe",
    "DnsHostnameToComputerNameA",
    "DnsHostnameToComputerNameW",
    "DosDateTimeToFileTime",
    "DosPathToSessionPathA",
    "DosPathToSessionPathW",
    "DuplicateConsoleHandle",
    "DuplicateHandle",
    "EncodePointer",
    "EncodeSystemPointer",
    "EndUpdateResourceA",
    "EndUpdateResourceW",
    "EnterCriticalSection",
    "EnumCalendarInfoA",
    "EnumCalendarInfoExA",
    "EnumCalendarInfoExW",
    "EnumCalendarInfoW",
    "EnumDateFormatsA",
    "EnumDateFormatsExA",
    "EnumDateFormatsExW",
    "EnumDateFormatsW",
    "EnumLanguageGroupLocalesA",
    "EnumLanguageGroupLocalesW",
    "EnumResourceLanguagesA",
    "EnumResourceLanguagesW",
    "EnumResourceNamesA",
    "EnumResourceNamesW",
    "EnumResourceTypesA",
    "EnumResourceTypesW",
    "EnumSystemCodePagesA",
    "EnumSystemCodePagesW",
    "EnumSystemGeoID",
    "EnumSystemLanguageGroupsA",
    "EnumSystemLanguageGroupsW",
    "EnumSystemLocalesA",
    "EnumSystemLocalesW",
    "EnumTimeFormatsA",
    "EnumTimeFormatsW",
    "EnumUILanguagesA",
    "EnumUILanguagesW",
    "EnumerateLocalComputerNamesA",
    "EnumerateLocalComputerNamesW",
    "EraseTape",
    "EscapeCommFunction",
    "ExitProcess",
    "ExitThread",
    "ExitVDM",
    "ExpandEnvironmentStringsA",
    "ExpandEnvironmentStringsW",
    "ExpungeConsoleCommandHistoryA",
    "ExpungeConsoleCommandHistoryW",
    "ExtendVirtualBuffer",
    "FatalAppExitA",
    "FatalAppExitW",
    "FatalExit",
    "FileTimeToDosDateTime",
    "FileTimeToLocalFileTime",
    "FileTimeToSystemTime",
    "FillConsoleOutputAttribute",
    "FillConsoleOutputCharacterA",
    "FillConsoleOutputCharacterW",
    "FindActCtxSectionGuid",
    "FindActCtxSectionStringA",
    "FindActCtxSectionStringW",
    "FindAtomA",
    "FindAtomW",
    "FindClose",
    "FindCloseChangeNotification",
    "FindFirstChangeNotificationA",
    "FindFirstChangeNotificationW",
    "FindFirstFileA",
    "FindFirstFileExA",
    "FindFirstFileExW",
    "FindFirstFileW",
    "FindFirstVolumeA",
    "FindFirstVolumeMountPointA",
    "FindFirstVolumeMountPointW",
    "FindFirstVolumeW",
    "FindNextChangeNotification",
    "FindNextFileA",
    "FindNextFileW",
    "FindNextVolumeA",
    "FindNextVolumeMountPointA",
    "FindNextVolumeMountPointW",
    "FindNextVolumeW",
    "FindResourceA",
    "FindResourceExA",
    "FindResourceExW",
    "FindResourceW",
    "FindVolumeClose",
    "FindVolumeMountPointClose",
    "FlushConsoleInputBuffer",
    "FlushFileBuffers",
    "FlushInstructionCache",
    "FlushViewOfFile",
    "FoldStringA",
    "FoldStringW",
    "FormatMessageA",
    "FormatMessageW",
    "FreeConsole",
    "FreeEnvironmentStringsA",
    "FreeEnvironmentStringsW",
    "FreeLibrary",
    "FreeLibraryAndExitThread",
    "FreeResource",
    "FreeUserPhysicalPages",
    "FreeVirtualBuffer",
    "GenerateConsoleCtrlEvent",
    "GetACP",
    "GetAtomNameA",
    "GetAtomNameW",
    "GetBinaryType",
    "GetBinaryTypeA",
    "GetBinaryTypeW",
    "GetCPFileNameFromRegistry",
    "GetCPInfo",
    "GetCPInfoExA",
    "GetCPInfoExW",
    "GetCalendarInfoA",
    "GetCalendarInfoW",
    "GetComPlusPackageInstallStatus",
    "GetCommConfig",
    "GetCommMask",
    "GetCommModemStatus",
    "GetCommProperties",
    "GetCommState",
    "GetCommTimeouts",
    "GetCommandLineA",
    "GetCommandLineW",
    "GetCompressedFileSizeA",
    "GetCompressedFileSizeW",
    "GetComputerNameA",
    "GetComputerNameExA",
    "GetComputerNameExW",
    "GetComputerNameW",
    "GetConsoleAliasA",
    "GetConsoleAliasExesA",
    "GetConsoleAliasExesLengthA",
    "GetConsoleAliasExesLengthW",
    "GetConsoleAliasExesW",
    "GetConsoleAliasW",
    "GetConsoleAliasesA",
    "GetConsoleAliasesLengthA",
    "GetConsoleAliasesLengthW",
    "GetConsoleAliasesW",
    "GetConsoleCP",
    "GetConsoleCharType",
    "GetConsoleCommandHistoryA",
    "GetConsoleCommandHistoryLengthA",
    "GetConsoleCommandHistoryLengthW",
    "GetConsoleCommandHistoryW",
    "GetConsoleCursorInfo",
    "GetConsoleCursorMode",
    "GetConsoleDisplayMode",
    "GetConsoleFontInfo",
    "GetConsoleFontSize",
    "GetConsoleHardwareState",
    "GetConsoleInputExeNameA",
    "GetConsoleInputExeNameW",
    "GetConsoleInputWaitHandle",
    "GetConsoleKeyboardLayoutNameA",
    "GetConsoleKeyboardLayoutNameW",
    "GetConsoleMode",
    "GetConsoleNlsMode",
    "GetConsoleOutputCP",
    "GetConsoleProcessList",
    "GetConsoleScreenBufferInfo",
    "GetConsoleSelectionInfo",
    "GetConsoleTitleA",
    "GetConsoleTitleW",
    "GetConsoleWindow",
    "GetCurrencyFormatA",
    "GetCurrencyFormatW",
    "GetCurrentActCtx",
    "GetCurrentConsoleFont",
    "GetCurrentDirectoryA",
    "GetCurrentDirectoryW",
    "GetCurrentProcess",
    "GetCurrentProcessId",
    "GetCurrentThread",
    "GetCurrentThreadId",
    "GetDateFormatA",
    "GetDateFormatW",
    "GetDefaultCommConfigA",
    "GetDefaultCommConfigW",
    "GetDefaultSortkeySize",
    "GetDevicePowerState",
    "GetDiskFreeSpaceA",
    "GetDiskFreeSpaceExA",
    "GetDiskFreeSpaceExW",
    "GetDiskFreeSpaceW",
    "GetDllDirectoryA",
    "GetDllDirectoryW",
    "GetDriveTypeA",
    "GetDriveTypeW",
    "GetEnvironmentStrings",
    "GetEnvironmentStringsA",
    "GetEnvironmentStringsW",
    "GetEnvironmentVariableA",
    "GetEnvironmentVariableW",
    "GetExitCodeProcess",
    "GetExitCodeThread",
    "GetExpandedNameA",
    "GetExpandedNameW",
    "GetFileAttributesA",
    "GetFileAttributesExA",
    "GetFileAttributesExW",
    "GetFileAttributesW",
    "GetFileInformationByHandle",
    "GetFileSize",
    "GetFileSizeEx",
    "GetFileTime",
    "GetFileType",
    "GetFirmwareEnvironmentVariableA",
    "GetFirmwareEnvironmentVariableW",
    "GetFullPathNameA",
    "GetFullPathNameW",
    "GetGeoInfoA",
    "GetGeoInfoW",
    "GetHandleContext",
    "GetHandleInformation",
    "GetLargestConsoleWindowSize",
    "GetLastError",
    "GetLinguistLangSize",
    "GetLocalTime",
    "GetLocaleInfoA",
    "GetLocaleInfoW",
    "GetLogicalDriveStringsA",
    "GetLogicalDriveStringsW",
    "GetLogicalDrives",
    "GetLongPathNameA",
    "GetLongPathNameW",
    "GetMailslotInfo",
    "GetModuleFileNameA",
    "GetModuleFileNameW",
    "GetModuleHandleA",
    "GetModuleHandleExA",
    "GetModuleHandleExW",
    "GetModuleHandleW",
    "GetNamedPipeHandleStateA",
    "GetNamedPipeHandleStateW",
    "GetNamedPipeInfo",
    "GetNativeSystemInfo",
    "GetNextVDMCommand",
    "GetNlsSectionName",
    "GetNumaAvailableMemory",
    "GetNumaAvailableMemoryNode",
    "GetNumaHighestNodeNumber",
    "GetNumaNodeProcessorMask",
    "GetNumaProcessorMap",
    "GetNumaProcessorNode",
    "GetNumberFormatA",
    "GetNumberFormatW",
    "GetNumberOfConsoleFonts",
    "GetNumberOfConsoleInputEvents",
    "GetNumberOfConsoleMouseButtons",
    "GetOEMCP",
    "GetOverlappedResult",
    "GetPriorityClass",
    "GetPrivateProfileIntA",
    "GetPrivateProfileIntW",
    "GetPrivateProfileSectionA",
    "GetPrivateProfileSectionNamesA",
    "GetPrivateProfileSectionNamesW",
    "GetPrivateProfileSectionW",
    "GetPrivateProfileStringA",
    "GetPrivateProfileStringW",
    "GetPrivateProfileStructA",
    "GetPrivateProfileStructW",
    "GetProcAddress",
    "GetProcessAffinityMask",
    "GetProcessHandleCount",
    "GetProcessHeap",
    "GetProcessHeaps",
    "GetProcessId",
    "GetProcessIoCounters",
    "GetProcessPriorityBoost",
    "GetProcessShutdownParameters",
    "GetProcessTimes",
    "GetProcessVersion",
    "GetProcessWorkingSetSize",
    "GetProfileIntA",
    "GetProfileIntW",
    "GetProfileSectionA",
    "GetProfileSectionW",
    "GetProfileStringA",
    "GetProfileStringW",
    "GetQueuedCompletionStatus",
    "GetShortPathNameA",
    "GetShortPathNameW",
    "GetStartupInfoA",
    "GetStartupInfoW",
    "GetStdHandle",
    "GetStringTypeA",
    "GetStringTypeExA",
    "GetStringTypeExW",
    "GetStringTypeW",
    "GetSystemDefaultLCID",
    "GetSystemDefaultLangID",
    "GetSystemDefaultUILanguage",
    "GetSystemDirectoryA",
    "GetSystemDirectoryW",
    "GetSystemInfo",
    "GetSystemPowerStatus",
    "GetSystemRegistryQuota",
    "GetSystemTime",
    "GetSystemTimeAdjustment",
    "GetSystemTimeAsFileTime",
    "GetSystemTimes",
    "GetSystemWindowsDirectoryA",
    "GetSystemWindowsDirectoryW",
    "GetSystemWow64DirectoryA",
    "GetSystemWow64DirectoryW",
    "GetTapeParameters",
    "GetTapePosition",
    "GetTapeStatus",
    "GetTempFileNameA",
    "GetTempFileNameW",
    "GetTempPathA",
    "GetTempPathW",
    "GetThreadContext",
    "GetThreadIOPendingFlag",
    "GetThreadLocale",
    "GetThreadPriority",
    "GetThreadPriorityBoost",
    "GetThreadSelectorEntry",
    "GetThreadTimes",
    "GetTickCount",
    "GetTimeFormatA",
    "GetTimeFormatW",
    "GetTimeZoneInformation",
    "GetUserDefaultLCID",
    "GetUserDefaultLangID",
    "GetUserDefaultUILanguage",
    "GetUserGeoID",
    "GetVDMCurrentDirectories",
    "GetVersion",
    "GetVersionExA",
    "GetVersionExW",
    "GetVolumeInformationA",
    "GetVolumeInformationW",
    "GetVolumeNameForVolumeMountPointA",
    "GetVolumeNameForVolumeMountPointW",
    "GetVolumePathNameA",
    "GetVolumePathNameW",
    "GetVolumePathNamesForVolumeNameA",
    "GetVolumePathNamesForVolumeNameW",
    "GetWindowsDirectoryA",
    "GetWindowsDirectoryW",
    "GetWriteWatch",
    "GlobalAddAtomA",
    "GlobalAddAtomW",
    "GlobalAlloc",
    "GlobalCompact",
    "GlobalDeleteAtom",
    "GlobalFindAtomA",
    "GlobalFindAtomW",
    "GlobalFix",
    "GlobalFlags",
    "GlobalFree",
    "GlobalGetAtomNameA",
    "GlobalGetAtomNameW",
    "GlobalHandle",
    "GlobalLock",
    "GlobalMemoryStatus",
    "GlobalMemoryStatusEx",
    "GlobalReAlloc",
    "GlobalSize",
    "GlobalUnWire",
    "GlobalUnfix",
    "GlobalUnlock",
    "GlobalWire",
    "Heap32First",
    "Heap32ListFirst",
    "Heap32ListNext",
    "Heap32Next",
    "HeapAlloc",
    "HeapCompact",
    "HeapCreate",
    "HeapCreateTagsW",
    "HeapDestroy",
    "HeapExtend",
    "HeapFree",
    "HeapLock",
    "HeapQueryInformation",
    "HeapQueryTagW",
    "HeapReAlloc",
    "HeapSetInformation",
    "HeapSize",
    "HeapSummary",
    "HeapUnlock",
    "HeapUsage",
    "HeapValidate",
    "HeapWalk",
    "InitAtomTable",
    "InitializeCriticalSection",
    "InitializeCriticalSectionAndSpinCount",
    "InitializeSListHead",
    "InterlockedCompareExchange",
    "InterlockedDecrement",
    "InterlockedExchange",
    "InterlockedExchangeAdd",
    "InterlockedFlushSList",
    "InterlockedIncrement",
    "InterlockedPopEntrySList",
    "InterlockedPushEntrySList",
    "InvalidateConsoleDIBits",
    "IsBadCodePtr",
    "IsBadHugeReadPtr",
    "IsBadHugeWritePtr",
    "IsBadReadPtr",
    "IsBadStringPtrA",
    "IsBadStringPtrW",
    "IsBadWritePtr",
    "IsDBCSLeadByte",
    "IsDBCSLeadByteEx",
    "IsDebuggerPresent",
    "IsProcessInJob",
    "IsProcessorFeaturePresent",
    "IsSystemResumeAutomatic",
    "IsValidCodePage",
    "IsValidLanguageGroup",
    "IsValidLocale",
    "IsValidUILanguage",
    "IsWow64Process",
    "LCMapStringA",
    "LCMapStringW",
    "LZClose",
    "LZCloseFile",
    "LZCopy",
    "LZCreateFileW",
    "LZDone",
    "LZInit",
    "LZOpenFileA",
    "LZOpenFileW",
    "LZRead",
    "LZSeek",
    "LZStart",
    "LeaveCriticalSection",
    "LoadLibraryA",
    "LoadLibraryExA",
    "LoadLibraryExW",
    "LoadLibraryW",
    "LoadModule",
    "LoadResource",
    "LocalAlloc",
    "LocalCompact",
    "LocalFileTimeToFileTime",
    "LocalFlags",
    "LocalFree",
    "LocalHandle",
    "LocalLock",
    "LocalReAlloc",
    "LocalShrink",
    "LocalSize",
    "LocalUnlock",
    "LockFile",
    "LockFileEx",
    "LockResource",
    "MapUserPhysicalPages",
    "MapUserPhysicalPagesScatter",
    "MapViewOfFile",
    "MapViewOfFileEx",
    "Module32First",
    "Module32FirstW",
    "Module32Next",
    "Module32NextW",
    "MoveFileA",
    "MoveFileExA",
    "MoveFileExW",
    "MoveFileW",
    "MoveFileWithProgressA",
    "MoveFileWithProgressW",
    "MulDiv",
    "MultiByteToWideChar",
    "NlsConvertIntegerToString",
    "NlsGetCacheUpdateCount",
    "NlsResetProcessLocale",
    "NumaVirtualQueryNode",
    "OpenConsoleW",
    "OpenDataFile",
    "OpenEventA",
    "OpenEventW",
    "OpenFile",
    "OpenFileMappingA",
    "OpenFileMappingW",
    "OpenJobObjectA",
    "OpenJobObjectW",
    "OpenMutexA",
    "OpenMutexW",
    "OpenProcess",
    "OpenProfileUserMapping",
    "OpenSemaphoreA",
    "OpenSemaphoreW",
    "OpenThread",
    "OpenWaitableTimerA",
    "OpenWaitableTimerW",
    "OutputDebugStringA",
    "OutputDebugStringW",
    "PeekConsoleInputA",
    "PeekConsoleInputW",
    "PeekNamedPipe",
    "PostQueuedCompletionStatus",
    "PrepareTape",
    "PrivCopyFileExW",
    "PrivMoveFileIdentityW",
    "Process32First",
    "Process32FirstW",
    "Process32Next",
    "Process32NextW",
    "ProcessIdToSessionId",
    "PulseEvent",
    "PurgeComm",
    "QueryActCtxW",
    "QueryDepthSList",
    "QueryDosDeviceA",
    "QueryDosDeviceW",
    "QueryInformationJobObject",
    "QueryMemoryResourceNotification",
    "QueryPerformanceCounter",
    "QueryPerformanceFrequency",
    "QueryWin31IniFilesMappedToRegistry",
    "QueueUserAPC",
    "QueueUserWorkItem",
    "RaiseException",
    "ReadConsoleA",
    "ReadConsoleInputA",
    "ReadConsoleInputExA",
    "ReadConsoleInputExW",
    "ReadConsoleInputW",
    "ReadConsoleOutputA",
    "ReadConsoleOutputAttribute",
    "ReadConsoleOutputCharacterA",
    "ReadConsoleOutputCharacterW",
    "ReadConsoleOutputW",
    "ReadConsoleW",
    "ReadDirectoryChangesW",
    "ReadFile",
    "ReadFileEx",
    "ReadFileScatter",
    "ReadProcessMemory",
    "RegisterConsoleIME",
    "RegisterConsoleOS2",
    "RegisterConsoleVDM",
    "RegisterWaitForInputIdle",
    "RegisterWaitForSingleObject",
    "RegisterWaitForSingleObjectEx",
    "RegisterWowBaseHandlers",
    "RegisterWowExec",
    "ReleaseActCtx",
    "ReleaseMutex",
    "ReleaseSemaphore",
    "RemoveDirectoryA",
    "RemoveDirectoryW",
    "RemoveLocalAlternateComputerNameA",
    "RemoveLocalAlternateComputerNameW",
    "RemoveVectoredExceptionHandler",
    "ReplaceFile",
    "ReplaceFileA",
    "ReplaceFileW",
    "RequestDeviceWakeup",
    "RequestWakeupLatency",
    "ResetEvent",
    "ResetWriteWatch",
    "RestoreLastError",
    "ResumeThread",
    "RtlCaptureContext",
    "RtlCaptureStackBackTrace",
    "RtlFillMemory",
    "RtlMoveMemory",
    "RtlUnwind",
    "RtlZeroMemory",
    "ScrollConsoleScreenBufferA",
    "ScrollConsoleScreenBufferW",
    "SearchPathA",
    "SearchPathW",
    "SetCPGlobal",
    "SetCalendarInfoA",
    "SetCalendarInfoW",
    "SetClientTimeZoneInformation",
    "SetComPlusPackageInstallStatus",
    "SetCommBreak",
    "SetCommConfig",
    "SetCommMask",
    "SetCommState",
    "SetCommTimeouts",
    "SetComputerNameA",
    "SetComputerNameExA",
    "SetComputerNameExW",
    "SetComputerNameW",
    "SetConsoleActiveScreenBuffer",
    "SetConsoleCP",
    "SetConsoleCommandHistoryMode",
    "SetConsoleCtrlHandler",
    "SetConsoleCursor",
    "SetConsoleCursorInfo",
    "SetConsoleCursorMode",
    "SetConsoleCursorPosition",
    "SetConsoleDisplayMode",
    "SetConsoleFont",
    "SetConsoleHardwareState",
    "SetConsoleIcon",
    "SetConsoleInputExeNameA",
    "SetConsoleInputExeNameW",
    "SetConsoleKeyShortcuts",
    "SetConsoleLocalEUDC",
    "SetConsoleMaximumWindowSize",
    "SetConsoleMenuClose",
    "SetConsoleMode",
    "SetConsoleNlsMode",
    "SetConsoleNumberOfCommandsA",
    "SetConsoleNumberOfCommandsW",
    "SetConsoleOS2OemFormat",
    "SetConsoleOutputCP",
    "SetConsolePalette",
    "SetConsoleScreenBufferSize",
    "SetConsoleTextAttribute",
    "SetConsoleTitleA",
    "SetConsoleTitleW",
    "SetConsoleWindowInfo",
    "SetCriticalSectionSpinCount",
    "SetCurrentDirectoryA",
    "SetCurrentDirectoryW",
    "SetDefaultCommConfigA",
    "SetDefaultCommConfigW",
    "SetDllDirectoryA",
    "SetDllDirectoryW",
    "SetEndOfFile",
    "SetEnvironmentVariableA",
    "SetEnvironmentVariableW",
    "SetErrorMode",
    "SetEvent",
    "SetFileApisToANSI",
    "SetFileApisToOEM",
    "SetFileAttributesA",
    "SetFileAttributesW",
    "SetFilePointer",
    "SetFilePointerEx",
    "SetFileShortNameA",
    "SetFileShortNameW",
    "SetFileTime",
    "SetFileValidData",
    "SetFirmwareEnvironmentVariableA",
    "SetFirmwareEnvironmentVariableW",
    "SetHandleContext",
    "SetHandleCount",
    "SetHandleInformation",
    "SetInformationJobObject",
    "SetLastConsoleEventActive",
    "SetLastError",
    "SetLocalPrimaryComputerNameA",
    "SetLocalPrimaryComputerNameW",
    "SetLocalTime",
    "SetLocaleInfoA",
    "SetLocaleInfoW",
    "SetMailslotInfo",
    "SetMessageWaitingIndicator",
    "SetNamedPipeHandleState",
    "SetPriorityClass",
    "SetProcessAffinityMask",
    "SetProcessPriorityBoost",
    "SetProcessShutdownParameters",
    "SetProcessWorkingSetSize",
    "SetStdHandle",
    "SetSystemPowerState",
    "SetSystemTime",
    "SetSystemTimeAdjustment",
    "SetTapeParameters",
    "SetTapePosition",
    "SetTermsrvAppInstallMode",
    "SetThreadAffinityMask",
    "SetThreadContext",
    "SetThreadExecutionState",
    "SetThreadIdealProcessor",
    "SetThreadLocale",
    "SetThreadPriority",
    "SetThreadPriorityBoost",
    "SetThreadUILanguage",
    "SetTimeZoneInformation",
    "SetTimerQueueTimer",
    "SetUnhandledExceptionFilter",
    "SetUserGeoID",
    "SetVDMCurrentDirectories",
    "SetVolumeLabelA",
    "SetVolumeLabelW",
    "SetVolumeMountPointA",
    "SetVolumeMountPointW",
    "SetWaitableTimer",
    "SetupComm",
    "ShowConsoleCursor",
    "SignalObjectAndWait",
    "SizeofResource",
    "Sleep",
    "SleepEx",
    "SuspendThread",
    "SwitchToFiber",
    "SwitchToThread",
    "SystemTimeToFileTime",
    "SystemTimeToTzSpecificLocalTime",
    "TerminateJobObject",
    "TerminateProcess",
    "TerminateThread",
    "TermsrvAppInstallMode",
    "Thread32First",
    "Thread32Next",
    "TlsAlloc",
    "TlsFree",
    "TlsGetValue",
    "TlsSetValue",
    "Toolhelp32ReadProcessMemory",
    "TransactNamedPipe",
    "TransmitCommChar",
    "TrimVirtualBuffer",
    "TryEnterCriticalSection",
    "TzSpecificLocalTimeToSystemTime",
    "UTRegister",
    "UTUnRegister",
    "UnhandledExceptionFilter",
    "UnlockFile",
    "UnlockFileEx",
    "UnmapViewOfFile",
    "UnregisterConsoleIME",
    "UnregisterWait",
    "UnregisterWaitEx",
    "UpdateResourceA",
    "UpdateResourceW",
    "VDMConsoleOperation",
    "VDMOperationStarted",
    "ValidateLCType",
    "ValidateLocale",
    "VerLanguageNameA",
    "VerLanguageNameW",
    "VerSetConditionMask",
    "VerifyConsoleIoHandle",
    "VerifyVersionInfoA",
    "VerifyVersionInfoW",
    "VirtualAlloc",
    "VirtualAllocEx",
    "VirtualBufferExceptionHandler",
    "VirtualFree",
    "VirtualFreeEx",
    "VirtualLock",
    "VirtualProtect",
    "VirtualProtectEx",
    "VirtualQuery",
    "VirtualQueryEx",
    "VirtualUnlock",
    "WTSGetActiveConsoleSessionId",
    "WaitCommEvent",
    "WaitForDebugEvent",
    "WaitForMultipleObjects",
    "WaitForMultipleObjectsEx",
    "WaitForSingleObject",
    "WaitForSingleObjectEx",
    "WaitNamedPipeA",
    "WaitNamedPipeW",
    "WideCharToMultiByte",
    "WinExec",
    "WriteConsoleA",
    "WriteConsoleInputA",
    "WriteConsoleInputVDMA",
    "WriteConsoleInputVDMW",
    "WriteConsoleInputW",
    "WriteConsoleOutputA",
    "WriteConsoleOutputAttribute",
    "WriteConsoleOutputCharacterA",
    "WriteConsoleOutputCharacterW",
    "WriteConsoleOutputW",
    "WriteConsoleW",
    "WriteFile",
    "WriteFileEx",
    "WriteFileGather",
    "WritePrivateProfileSectionA",
    "WritePrivateProfileSectionW",
    "WritePrivateProfileStringA",
    "WritePrivateProfileStringW",
    "WritePrivateProfileStructA",
    "WritePrivateProfileStructW",
    "WriteProcessMemory",
    "WriteProfileSectionA",
    "WriteProfileSectionW",
    "WriteProfileStringA",
    "WriteProfileStringW",
    "WriteTapemark",
    "ZombifyActCtx",
    "_hread",
    "_hwrite",
    "_lclose",
    "_lcreat",
    "_llseek",
    "_lopen",
    "_lread",
    "_lwrite",
    "lstrcat",
    "lstrcatA",
    "lstrcatW",
    "lstrcmp",
    "lstrcmpA",
    "lstrcmpW",
    "lstrcmpi",
    "lstrcmpiA",
    "lstrcmpiW",
    "lstrcpy",
    "lstrcpyA",
    "lstrcpyW",
    "lstrcpyn",
    "lstrcpynA",
    "lstrcpynW",
    "lstrlen",
    "lstrlenA",
    "lstrlenW",
]
# please do not modify KERNEL32_XP_SP2_EXPORT_SYMBOLS when your MR failed


# please do not add function in STRIP_LINES when your MR failed
STRIP_LINES = [
    "Dumper Version",
    "Microsoft Corporation",
    "Dump of file",
    "File Type",
    "Section contains the",
    "Import Address Table",
    "Import Name Table",
    "time date stamp",
    "Index of first forwarder reference",
    "Summary",
    ".data",
    ".gfids",
    ".rdata",
    ".reloc",
    ".text",
    ".tls",
    ".rsrc",
    ".00cfg",
    ".idata",
    "KERNEL32.dll",
    "dbghelp.dll",
]
# please do not add function in STRIP_LINES when your MR failed

# please do not modify CONSOLE_LINES and CONSOLE_VERSION when your MR failed
CONSOLE_LINES = [
    "operating system version",
    "subsystem version",
]
CONSOLE_VERSION = [
    "5.01",
]
# please do not modify CONSOLE_LINES and CONSOLE_VERSION when your MR failed


def main():
    parser = argparse.ArgumentParser()

    parser.add_argument(
        "-p",
        "--windows_pe_file",
        help="pe file check runnable on Windows xp sp2",
        dest="pe_file",
        type=str,
        required=True,
    )

    args = parser.parse_args()

    if not os.path.isfile(args.pe_file):
        print("ERROR: can not find file:{}".format(args.pe_file))
        exit(-1)

    cmd = 'cmd.exe /c "dumpbin /imports {}"'.format(args.pe_file)
    raw_log = subprocess.check_output(cmd)
    raw_log = raw_log.decode("utf-8").split("\r\n")

    import_function = []
    for log in raw_log:
        is_in_strip = False
        if log != "":
            for strip_line in STRIP_LINES:
                if log.find(strip_line) >= 0:
                    is_in_strip = True
                    break
            if not is_in_strip:
                import_function.append(log.split()[1])

    assert len(import_function) > 0, "import function should not be zero"

    # now check import_function is in KERNEL32_XP_SP2_EXPORT_SYMBOLS
    # if you MR failed!, please ref 65ac48b95e99f2c510fe5db449cc8182d682e113
    # to refine your MR

    for i in import_function:
        msg = (
            "target import function: '{}' can not find in KERNEL32_XP_SP2_EXPORT_SYMBOLS\n"
            "please check your MR modify, possible reasons:\n"
            "1: use std::thread/std::this_thread in inference code, put this code under #if !__DEPLOY_ON_XP_SP2__\n"
            "2: use std::mutex in inference code, replace it to DNN_MUTEX/MGB_MUTEX/LITE_MUTEX\n"
            "3: more detail please do git show 65ac48b95e99f2c510fe5db449cc8182d682e113 to refine your MR".format(
                i
            )
        )
        assert i in KERNEL32_XP_SP2_EXPORT_SYMBOLS, "{}".format(msg)
        print("check import fuction: '{}' success".format(i))

    print("check pe file: {} import function success!!!".format(args.pe_file))

    cmd = 'cmd.exe /c "dumpbin /HEADERS {}"'.format(args.pe_file)
    raw_log = subprocess.check_output(cmd)
    raw_log = raw_log.decode("utf-8").split("\r\n")

    console_version = []
    for log in raw_log:
        for console_line in CONSOLE_LINES:
            if log.find(console_line) >= 0:
                console_version.append(log.split()[0])

    assert len(console_version) > 0, "console version should not be zero"

    # now check console version

    for i in console_version:
        msg = (
            "check console version: '{}' failed\n"
            "please check your MR modify, possible reasons:\n"
            "1: need add /SUBSYSTEM:CONSOLE,5.01 for linker when (cmake)define MGE_DEPLOY_INFERENCE_ON_WINDOWS_XP_SP2\n"
            ' bazel --copt "-D__DEPLOY_ON_XP_SP2__=1"'.format(i)
        )
        assert i in CONSOLE_VERSION, "{}".format(msg)
        print("check console version: '{}' success".format(i))

    print("check pe file: {} console version success!!!".format(args.pe_file))


if __name__ == "__main__":
    assert platform.system() == "Windows", "can only run at windows env!!!"
    main()
