C++ 如何定位“a”中出现错误的位置;PackageManager.AddPackageAsync“;方法调用?
我正在调试一个部署Windows Metro应用程序包(“.Appx”文件)的示例应用程序。它调用WinRT方法“”,该方法失败,并显示详细的错误代码文本(在操作完成后从调用返回值中检索): 错误0x80070002:由于出现错误,Windows无法注册程序包 内部错误或内存不足 我的目标是找到WinRT调用中出现此错误的确切位置。我认为实现这一点的最佳方法是找到错误代码的设置位置。我以前用过旧的简单Win32 API,但现在用这个新的基于com的复杂异步接口,我完全迷路了 可以找到示例项目文件。其主要功能如下所示:C++ 如何定位“a”中出现错误的位置;PackageManager.AddPackageAsync“;方法调用?,c++,debugging,assembly,windows-runtime,ida,C++,Debugging,Assembly,Windows Runtime,Ida,我正在调试一个部署Windows Metro应用程序包(“.Appx”文件)的示例应用程序。它调用WinRT方法“”,该方法失败,并显示详细的错误代码文本(在操作完成后从调用返回值中检索): 错误0x80070002:由于出现错误,Windows无法注册程序包 内部错误或内存不足 我的目标是找到WinRT调用中出现此错误的确切位置。我认为实现这一点的最佳方法是找到错误代码的设置位置。我以前用过旧的简单Win32 API,但现在用这个新的基于com的复杂异步接口,我完全迷路了 可以找到示例项目文件
[MTAThread]
int __cdecl main(Platform::Array<String^>^ args)
{
wcout << L"Copyright (c) Microsoft Corporation. All rights reserved." << endl;
wcout << L"AddPackage sample" << endl << endl;
if (args->Length < 2)
{
wcout << "Usage: AddPackageSample.exe packageUri" << endl;
return 1;
}
HANDLE completedEvent = nullptr;
int returnValue = 0;
String^ inputPackageUri = args[1];
try
{
completedEvent = CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS);
if (completedEvent == nullptr)
{
wcout << L"CreateEvent Failed, error code=" << GetLastError() << endl;
returnValue = 1;
}
else
{
auto packageUri = ref new Uri(inputPackageUri);
auto packageManager = ref new PackageManager();
auto deploymentOperation = packageManager->AddPackageAsync(packageUri, nullptr, DeploymentOptions::None);
deploymentOperation->Completed =
ref new AsyncOperationWithProgressCompletedHandler<DeploymentResult^, DeploymentProgress>(
[&completedEvent](IAsyncOperationWithProgress<DeploymentResult^, DeploymentProgress>^ operation, AsyncStatus)
{
SetEvent(completedEvent);
});
wcout << L"Installing package " << inputPackageUri->Data() << endl;
wcout << L"Waiting for installation to complete..." << endl;
WaitForSingleObject(completedEvent, INFINITE);
if (deploymentOperation->Status == AsyncStatus::Error) //Here I decided to track "deploymentOperation->Status"
{
auto deploymentResult = deploymentOperation->GetResults();
wcout << L"Installation Error: " << deploymentOperation->ErrorCode.Value << endl;
wcout << L"Detailed Error Text: " << deploymentResult->ErrorText->Data() << endl;
}
else if (deploymentOperation->Status == AsyncStatus::Canceled)
{
wcout << L"Installation Canceled" << endl;
}
else if (deploymentOperation->Status == AsyncStatus::Completed)
{
wcout << L"Installation succeeded!" << endl;
}
}
}
catch (Exception^ ex)
{
wcout << L"AddPackageSample failed, error message: " << ex->ToString()->Data() << endl;
returnValue = 1;
}
if (completedEvent != nullptr)
CloseHandle(completedEvent);
return returnValue;
}
ntdll中调用“NtGetCompleteWnfStateSubscription”函数的代码,初始化具有此结构类型的成员的变量(在程序集中,IDA PRO生成):
上面的代码实际上被调用了3次,但是使用了相同的“esi”指针。现在我的问题是如何找到使用这个函数将错误代码设置为检索到的位置。我尝试捕获ntdll中的大部分函数,看起来像这样做,但没有成功。由于某些奇怪的原因,我无法调试NtGetCompleteWnfStateSubscription。任何建议都会有帮助。我使用的是IDA PRO 6.5,VS 2013 U1,Windows 8.1 x64 U1
编辑:如果您不想为特定于问题的详细信息而烦恼,我的一般问题是如何定位WinRT异步方法设置“IAsyncInfo::Status”属性的位置,或者在执行过程中出现错误时调用什么函数或方法。这看起来很有趣。希望有人能提供答案。要调试
NtGetCompleteWnfStateSubscription
您需要一个内核调试器。我知道这一点,但我认为还有另一种方法。
struct Unknown
{
AsyncStatus /*? 32bit long*/ dw0; // it was set to '3' during the current operation as the AsyncStatus::error enum value so I think it should belong to it
DWORD dw4; //was set to 0x5F
DWORD dw8; //was set to 0x80073CF6 (some generic error)
} ;
ntdll.dll:77906200 loc_77906200: ; CODE XREF: ntdll.dll:ntdll_strncpy_s+1A3j
ntdll.dll:77906200 push 1030h
ntdll.dll:77906205 push esi ; the variable pointer
ntdll.dll:77906206 push edi
ntdll.dll:77906207 push eax
ntdll.dll:77906208 lea eax, [ebp-0Ch]
ntdll.dll:7790620B push eax
ntdll.dll:7790620C push ebx
ntdll.dll:7790620D call near ptr ntdll_NtGetCompleteWnfStateSubscription
ntdll.dll:77906212 test eax, eax ; now "[esi+2Ch] + esi" contains data from the "Unkown" structure and contains the operation error data
ntdll.dll:77906214 jns short loc_7790623F