Когда вы вызываете WinExec для запуска .exe, я получаю возвращаемое значение 0x21.
Согласно MSDN, возвращаемое значение, превышающее 31 (0x1F), означает, что функция выполнена успешно.
Но что это означает 0x21, почему он не возвратил мне другого значения?WinExec Return 0x21, но что именно это означает?
ответ
Не полезно знать, что это значит. Это деталь реализации. Даже если бы вы знали, что это значит для этой версии, значение может измениться в следующей версии. Как программист, вас интересует только программирование против интерфейса, а не базовая реализация.
Однако, если вы действительно заинтересованы, я возьму вас через подход, который я бы предпринял для обратной инженерии функции. В моей системе, WinExec
разбирают на это:
764F2C21 > 8BFF MOV EDI,EDI
764F2C23 55 PUSH EBP
764F2C24 8BEC MOV EBP,ESP
764F2C26 81EC 80000000 SUB ESP,80
764F2C2C 53 PUSH EBX
764F2C2D 8B5D 0C MOV EBX,DWORD PTR SS:[EBP+C]
764F2C30 56 PUSH ESI
764F2C31 57 PUSH EDI
764F2C32 33FF XOR EDI,EDI
764F2C34 47 INC EDI
764F2C35 33F6 XOR ESI,ESI
764F2C37 85DB TEST EBX,EBX
764F2C39 79 4F JNS SHORT kernel32.764F2C8A
764F2C3B 8D45 FC LEA EAX,DWORD PTR SS:[EBP-4]
764F2C3E 50 PUSH EAX
764F2C3F 56 PUSH ESI
764F2C40 57 PUSH EDI
764F2C41 8D45 C8 LEA EAX,DWORD PTR SS:[EBP-38]
764F2C44 50 PUSH EAX
764F2C45 C745 FC 20000000 MOV DWORD PTR SS:[EBP-4],20
764F2C4C E8 90BE0200 CALL <JMP.&API-MS-Win-Core-ProcessThread>
764F2C51 85C0 TEST EAX,EAX
764F2C53 0F84 D2000000 JE kernel32.764F2D2B
764F2C59 56 PUSH ESI
764F2C5A 56 PUSH ESI
764F2C5B 6A 04 PUSH 4
764F2C5D 8D45 F8 LEA EAX,DWORD PTR SS:[EBP-8]
764F2C60 50 PUSH EAX
764F2C61 68 01000600 PUSH 60001
764F2C66 56 PUSH ESI
764F2C67 8D45 C8 LEA EAX,DWORD PTR SS:[EBP-38]
764F2C6A 50 PUSH EAX
764F2C6B C745 0C 00000800 MOV DWORD PTR SS:[EBP+C],80000
764F2C72 897D F8 MOV DWORD PTR SS:[EBP-8],EDI
764F2C75 E8 5CBE0200 CALL <JMP.&API-MS-Win-Core-ProcessThread>
764F2C7A 85C0 TEST EAX,EAX
764F2C7C 0F84 95000000 JE kernel32.764F2D17
764F2C82 8D45 C8 LEA EAX,DWORD PTR SS:[EBP-38]
764F2C85 8945 C4 MOV DWORD PTR SS:[EBP-3C],EAX
764F2C88 EB 03 JMP SHORT kernel32.764F2C8D
764F2C8A 8975 0C MOV DWORD PTR SS:[EBP+C],ESI
764F2C8D 6A 44 PUSH 44
764F2C8F 8D45 80 LEA EAX,DWORD PTR SS:[EBP-80]
764F2C92 56 PUSH ESI
764F2C93 50 PUSH EAX
764F2C94 E8 B5E9F7FF CALL <JMP.&ntdll.memset>
764F2C99 83C4 0C ADD ESP,0C
764F2C9C 33C0 XOR EAX,EAX
764F2C9E 3975 0C CMP DWORD PTR SS:[EBP+C],ESI
764F2CA1 897D AC MOV DWORD PTR SS:[EBP-54],EDI
764F2CA4 0F95C0 SETNE AL
764F2CA7 66:895D B0 MOV WORD PTR SS:[EBP-50],BX
764F2CAB 8D0485 44000000 LEA EAX,DWORD PTR DS:[EAX*4+44]
764F2CB2 8945 80 MOV DWORD PTR SS:[EBP-80],EAX
764F2CB5 8D45 E8 LEA EAX,DWORD PTR SS:[EBP-18]
764F2CB8 50 PUSH EAX
764F2CB9 8D45 80 LEA EAX,DWORD PTR SS:[EBP-80]
764F2CBC 50 PUSH EAX
764F2CBD 56 PUSH ESI
764F2CBE 56 PUSH ESI
764F2CBF FF75 0C PUSH DWORD PTR SS:[EBP+C]
764F2CC2 56 PUSH ESI
764F2CC3 56 PUSH ESI
764F2CC4 56 PUSH ESI
764F2CC5 FF75 08 PUSH DWORD PTR SS:[EBP+8]
764F2CC8 56 PUSH ESI
764F2CC9 E8 A4E3F7FF CALL kernel32.CreateProcessA
764F2CCE 85C0 TEST EAX,EAX
764F2CD0 74 27 JE SHORT kernel32.764F2CF9
764F2CD2 A1 3C005476 MOV EAX,DWORD PTR DS:[7654003C]
764F2CD7 3BC6 CMP EAX,ESI
764F2CD9 74 0A JE SHORT kernel32.764F2CE5
764F2CDB 68 30750000 PUSH 7530
764F2CE0 FF75 E8 PUSH DWORD PTR SS:[EBP-18]
764F2CE3 FFD0 CALL EAX
764F2CE5 FF75 E8 PUSH DWORD PTR SS:[EBP-18]
764F2CE8 8B35 A0054776 MOV ESI,DWORD PTR DS:[<&ntdll.NtClose>] ; ntdll.ZwClose
764F2CEE FFD6 CALL ESI
764F2CF0 FF75 EC PUSH DWORD PTR SS:[EBP-14]
764F2CF3 FFD6 CALL ESI
764F2CF5 6A 21 PUSH 21
764F2CF7 EB 1D JMP SHORT kernel32.764F2D16
764F2CF9 E8 C9E4F7FF CALL <JMP.&API-MS-Win-Core-ErrorHandling>
764F2CFE 48 DEC EAX
764F2CFF 48 DEC EAX
764F2D00 74 12 JE SHORT kernel32.764F2D14
764F2D02 48 DEC EAX
764F2D03 74 0B JE SHORT kernel32.764F2D10
764F2D05 2D BE000000 SUB EAX,0BE
764F2D0A 75 0B JNZ SHORT kernel32.764F2D17
764F2D0C 6A 0B PUSH 0B
764F2D0E EB 06 JMP SHORT kernel32.764F2D16
764F2D10 6A 03 PUSH 3
764F2D12 EB 02 JMP SHORT kernel32.764F2D16
764F2D14 6A 02 PUSH 2
764F2D16 5E POP ESI
764F2D17 F745 0C 00000800 TEST DWORD PTR SS:[EBP+C],80000
764F2D1E 74 09 JE SHORT kernel32.764F2D29
764F2D20 8D45 C8 LEA EAX,DWORD PTR SS:[EBP-38]
764F2D23 50 PUSH EAX
764F2D24 E8 A2BD0200 CALL <JMP.&API-MS-Win-Core-ProcessThread>
764F2D29 8BC6 MOV EAX,ESI
764F2D2B 5F POP EDI
764F2D2C 5E POP ESI
764F2D2D 5B POP EBX
764F2D2E C9 LEAVE
764F2D2F C2 0800 RETN 8
Конвенция вызова используется под Win32 является stdcall
, который предписывает возвращаемые значения проводиться в EAX
. В случае WinExec
имеется только один выход из функции (0x764F2D2F
). Трассировка оттуда, EAX устанавливается (по крайней мере, когда возвращение 0x21):
764F2D29 8BC6 MOV EAX,ESI
Трассировка еще дальше назад, сам по себе ESI
устанавливается от POP ESI
, который выскакивает в верхней части стека в ESI
. Значение этого зависит от того, что ранее было нажато в стек.В случае 0x21, это происходит при:
764F2CF5 6A 21 PUSH 21
Сразу же после этого, JMP делается на POP ESI
. Как мы дошли до PUSH 21
, интересно только после вызова CreateProcess
.
764F2CC9 E8 A4E3F7FF CALL kernel32.CreateProcessA
764F2CCE 85C0 TEST EAX,EAX
764F2CD0 74 27 JE SHORT kernel32.764F2CF9
764F2CD2 A1 3C005476 MOV EAX,DWORD PTR DS:[7654003C]
764F2CD7 3BC6 CMP EAX,ESI
764F2CD9 74 0A JE SHORT kernel32.764F2CE5
764F2CDB 68 30750000 PUSH 7530
764F2CE0 FF75 E8 PUSH DWORD PTR SS:[EBP-18]
764F2CE3 FFD0 CALL EAX
764F2CE5 FF75 E8 PUSH DWORD PTR SS:[EBP-18]
764F2CE8 8B35 A0054776 MOV ESI,DWORD PTR DS:[<&ntdll.NtClose>] ; ntdll.ZwClose
764F2CEE FFD6 CALL ESI
764F2CF0 FF75 EC PUSH DWORD PTR SS:[EBP-14]
764F2CF3 FFD6 CALL ESI
764F2CF5 6A 21 PUSH 21
Чтобы увидеть, как путь приведет вас к PUSH 21
, наблюдать различные ветви. Первым происходит:
764F2CD0 74 27 JE SHORT kernel32.764F2CF9
Это говорит, если CreateProcess
возвращается 0, вызовите Win-Core-ErrorHandling
. Значения возврата затем устанавливаются по-разному (0x2, 0x3 и 0xB - все возможные возвращаемые значения, если CreateProcess
не удалось).
Следующая ветвь намного менее очевидно, перепроектировать:
764F2CD9 74 0A JE SHORT kernel32.764F2CE5
Что она делает для чтения адреса памяти, который, вероятно, содержит указатель на функцию (мы знаем это, потому что результат чтения называется позже на). Этот JE
просто указывает, нужно ли вообще выполнять этот вызов. Независимо от того, сделан ли звонок, следующим шагом является вызов ZwClose
(дважды). Наконец, возвращается 0x21.
Таким образом, один простой способ взглянуть на это, когда CreateProcess
преуспевает, возвращается 0x21, в противном случае возвращаются 0x2, 0x3 или 0xB. Это не означает, что это единственные возвращаемые значения. Например, 0x0 также может быть возвращено из ветки на 0x764F2C53
(в этом случае ESI не используется одинаково). Есть еще несколько возможных возвращаемых значений, но я оставлю их для вас, чтобы заглянуть в себя.
Что я показал вам, как сделать очень мелкий анализ WinExec
специально для возврата 0x21. Если вы хотите узнать больше, вам нужно больше толкнуть и попытаться понять с более высокого уровня, что происходит. Вы сможете узнать намного больше, просто нарушив функцию и пройдя через нее (таким образом вы сможете наблюдать за данными).
Еще один способ посмотреть на Wine source, где кто-то уже сделал всю тяжелую работу за вас:
UINT WINAPI WinExec(LPCSTR lpCmdLine, UINT nCmdShow)
{
PROCESS_INFORMATION info;
STARTUPINFOA startup;
char *cmdline;
UINT ret;
memset(&startup, 0, sizeof(startup));
startup.cb = sizeof(startup);
startup.dwFlags = STARTF_USESHOWWINDOW;
startup.wShowWindow = nCmdShow;
/* cmdline needs to be writable for CreateProcess */
if (!(cmdline = HeapAlloc(GetProcessHeap(), 0, strlen(lpCmdLine)+1))) return 0;
strcpy(cmdline, lpCmdLine);
if (CreateProcessA(NULL, cmdline, NULL, NULL, FALSE,
0, NULL, NULL, &startup, &info))
{
/* Give 30 seconds to the app to come up */
if (wait_input_idle(info.hProcess, 30000) == WAIT_FAILED)
WARN("WaitForInputIdle failed: Error %d\n", GetLastError());
ret = 33;
/* Close off the handles */
CloseHandle(info.hThread);
CloseHandle(info.hProcess);
}
else if ((ret = GetLastError()) >= 32)
{
FIXME("Strange error set by CreateProcess: %d\n", ret);
ret = 11;
}
HeapFree(GetProcessHeap(), 0, cmdline);
return ret;
}
33d является 0x21 так что это на самом деле просто подтверждает плоды нашего предыдущего анализа ,
Что касается причины, по которой возвращается 0x21, я предполагаю, что, возможно, существует более внутренняя документация, которая делает ее более полезной в некотором роде.
Кроме этого это означает успех, значение возвращаемого значения не определено. Возможно, он был выбран таким образом, чтобы устаревшие приложения хорошо работали с этим конкретным значением. Одно можно сказать наверняка: есть более важные вещи, о которых нужно беспокоиться!
http://msdn.microsoft.com/en-us/library/windows/desktop/ms687393(v=vs.85).aspx
EDIT: Этот ответ является неправильным, потому что результат в OP не является кодом ошибки. Я ошибочно подумал, что было сказано, что это код ошибки. Я по-прежнему думаю, что практическая информация ниже может быть полезна, плюс то, что может быть полезно увидеть, что может привести к неправильному предположению, поэтому я даю ей ответ.
Если вы установили Visual Studio (полный или экспресс-выпуск), то у вас есть инструмент под названием
errlook
, которая использует функцию
FormatMessage
API, чтобы сказать вам, что код ошибки или
HRESULT
означает значение.
В этом случае
Процесс не может получить доступ к файлу, так как другой процесс заблокировал часть файла.
Вы можете сделать это вручную, просмотрев файл <winerror.h>
. Например, введите #include
в исходном файле C++ в Visual Studio, затем щелкните правой кнопкой мыши и попросите его открыть заголовок. Где вы находите, что
//
// MessageId: ERROR_LOCK_VIOLATION
//
// MessageText:
//
// The process cannot access the file because another process has locked a portion of the file.
//
#define ERROR_LOCK_VIOLATION 33L
Кстати, WinExec
просто старая функция совместимости. Предпочтительно использовать ShellExecute
или CreateProcess
. Функция ShellExecute
может играть более красиво с Windows Vista и 7 User Access Control, и ее проще использовать, поэтому она обычно предпочтительнее.
Downvoted, потому что это не код ошибки! –
@Frederik: спасибо, я добавлю, что это неправильно. :-) –
Хм, это была не очень хорошая идея. Это был аттрактор нисходящего потока. Теперь только пользователи высокой репутации, которые не нуждаются в этом, могут видеть эту информацию. –
- 1. Что именно означает $ (...). Map() return?
- 2. Что именно означает это определение структуры?
- 3. Что именно это означает в C#?
- 4. Что именно это означает, когда $ _FILES пуст?
- 5. Свойство «user.dir» Java - что именно это означает?
- 6. Что именно это означает в контроллере AngularJS?
- 7. Что именно это означает в Python?
- 8. Что именно означает => означает?
- 9. Что именно означает «эффективный»
- 10. Что именно означает «закрытие»?
- 11. Что именно означает IQueryable?
- 12. Что именно означает ERROR_INVALID_ORDINAL?
- 13. Что именно тело означает DKIM
- 14. Что именно означает $ {...} в perl?
- 15. Что именно означает struct.calcsize ('P')?
- 16. Что именно означает этот URL?
- 17. что именно NSUrlConnection ASynchronous означает?
- 18. Что означает «return !! userId»
- 19. Kotlin: Что означает «return @»?
- 20. NIO: Что именно означает, что SelectionKey готов?
- 21. Что именно это означает? Коллекция <? extends E> c
- 22. Создание экземпляра шаблона на C++, что именно это означает?
- 23. Что именно означает .pipe() в глотке?
- 24. Что означает «return;» означает в javascript?
- 25. Что означает «return @ [blah, blah] [self.foo]» означает?
- 26. Что именно означает «* =» в программировании на С?
- 27. Что означает это `_time_independent_equals`?
- 28. Что означает «return false»; делать?
- 29. Что именно означает «закрытие» в JavaScript?
- 30. В Ruby, что именно означает tLABEL?
По какой-либо причине вы не можете использовать 'CreateProcess'? – Konrad
* Исторически * под win16 он перенастроил hinstance. –