Windows NT 系列作業系統透過 Virtual DOS Machine (VDM) 執行 16 位 Windows 應用程式。`VDMDBG.dll` (Platform SDK 附贈) 提供一組 API 列舉、建立、終止 VDM 內的 16 位任務,適用於偵錯工具、工作管理員等系統級工具開發。
| 函式 | 用途 |
|---|---|
| VDMEnumProcessWOW | 列舉所有執行 16 位 Windows 任務的 VDM (ntvdm.exe) |
| VDMEnumTaskWOW / Ex | 列舉指定 VDM 內的 16 位任務 |
| VDMStartTaskInWOW | 在指定 VDM 中啟動 16 位應用程式 |
| VDMTerminateTaskWOW | 終止指定 VDM 內的 16 位任務 |
#include
#include
#include
// 回呼函式:處理每個 VDM
BOOL WINAPI ProcessEnumProc(DWORD dwProcessId, DWORD dwAttrib, LPARAM lParam)
{
printf("\nVDM Process ID: %lu\n", dwProcessId);
// 列舉該 VDM 內的任務
VDMEnumTaskWOWEx(dwProcessId, TaskEnumProcEx, 0);
return FALSE; // 繼續列舉
}
// 回呼函式:處理每個 16 位任務
BOOL WINAPI TaskEnumProcEx(DWORD dwThreadId, WORD hMod16, WORD hTask16,
PSZ pszModName, PSZ pszFileName, LPARAM lParam)
{
printf(" Thread ID: %lu\n", dwThreadId);
printf(" Module Handle: %u\n", hMod16);
printf(" Task Handle: %u\n", hTask16);
printf(" Module Name: %s\n", pszModName);
printf(" File Name: %s\n", pszFileName);
return FALSE; // 繼續列舉
}
int main()
{
printf("Enumerating all 16-bit Windows tasks...\n");
VDMEnumProcessWOW(ProcessEnumProc, 0);
return 0;
}
// 在第一個找到的 VMD 中啟動計算機
VDMEnumProcessWOW([](DWORD pid, DWORD, LPARAM) -> BOOL {
VDMStartTaskInWOW(pid, "calc.exe", SW_SHOW);
return TRUE; // 只啟動第一個 VDM 即停止列舉
}, 0);
// 先列舉取得 hTask16,再終止
VDMEnumTaskWOWEx(dwVdmPid, [](DWORD, WORD, WORD hTask, PSZ, PSZ, LPARAM) -> BOOL {
if (strcmp(pszModName, "notepad") == 0) {
VDMTerminateTaskWOW(dwVdmPid, hTask);
return TRUE; // 找到即停止
}
return FALSE;
}, 0);
// 1. 取得所有 WOW VDM PID
std::set wowPids;
VDMEnumProcessWOW([](DWORD pid, DWORD, LPARAM p) -> BOOL {
static_cast*>(p)->insert(pid);
return FALSE;
}, (LPARAM)&wowPids);
// 2. 列舉所有 ntvdm.exe (PSAPI)
DWORD pids[1024], cbNeeded;
EnumProcesses(pids, sizeof(pids), &cbNeeded);
for (int i = 0; i < cbNeeded/sizeof(DWORD); ++i) {
HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, FALSE, pids[i]);
TCHAR name[MAX_PATH];
GetModuleBaseName(h, NULL, name, MAX_PATH);
if (_tcsicmp(name, _T("ntvdm.exe")) == 0 && !wowPids.count(pids[i])) {
printf("DOS VDM found: PID=%lu\n", pids[i]);
}
CloseHandle(h);
}
Windows 10/11 已移除 NTVDM (x64 版本),16 位應用無法原生執行。建議: