Commit 8609fef5 authored by Rémi Bernon's avatar Rémi Bernon Committed by Alexandre Julliard

windows.applicationmodel/tests: Test IPackageManager_RegisterPackageAsync.

parent 19c1cc1c
TESTDLL = windows.applicationmodel.dll
IMPORTS = combase
IMPORTS = combase advapi32
C_SRCS = \
model.c
application_EXTRADLLFLAGS = -mconsole
SOURCES = \
application.c \
model.c \
resource.rc
/*
* Copyright (C) 2023 Rémi Bernon for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#if 0
#pragma makedep testdll
#endif
#define COBJMACROS
#include <stddef.h>
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
int main( int argc, char const *argv[] )
{
return 0;
}
<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities">
<Identity Name="WineTest" Publisher="CN=Wine, O=The Wine Project, C=US" Version="1.0.0.0" ProcessorArchitecture="neutral" />
<Properties>
<DisplayName>WineTest</DisplayName>
<PublisherDisplayName>The Wine Project</PublisherDisplayName>
<Description>Reserved</Description>
<Logo>logo.png</Logo>
</Properties>
<Resources>
<Resource Language="en-us" />
</Resources>
<Dependencies>
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.0.0" MaxVersionTested="10.0.65535.0" />
</Dependencies>
<Capabilities>
<rescap:Capability Name="runFullTrust" />
</Capabilities>
<Applications>
<Application Id="WineTest" Executable="application.exe" EntryPoint="Windows.FullTrustApplication">
<uap:VisualElements BackgroundColor="transparent" DisplayName="WineTest" Square150x150Logo="logo.png" Square44x44Logo="logo.png" Description="WineTest" />
</Application>
</Applications>
</Package>
......@@ -38,6 +38,94 @@
#include "wine/test.h"
#define DEFINE_ASYNC_COMPLETED_HANDLER( name, iface_type, async_type ) \
struct name \
{ \
iface_type iface_type##_iface; \
LONG refcount; \
BOOL invoked; \
HANDLE event; \
}; \
\
static HRESULT WINAPI name##_QueryInterface( iface_type *iface, REFIID iid, void **out ) \
{ \
if (IsEqualGUID( iid, &IID_IUnknown ) || IsEqualGUID( iid, &IID_IAgileObject ) || \
IsEqualGUID( iid, &IID_##iface_type )) \
{ \
IUnknown_AddRef( iface ); \
*out = iface; \
return S_OK; \
} \
\
trace( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); \
*out = NULL; \
return E_NOINTERFACE; \
} \
\
static ULONG WINAPI name##_AddRef( iface_type *iface ) \
{ \
struct name *impl = CONTAINING_RECORD( iface, struct name, iface_type##_iface ); \
return InterlockedIncrement( &impl->refcount ); \
} \
\
static ULONG WINAPI name##_Release( iface_type *iface ) \
{ \
struct name *impl = CONTAINING_RECORD( iface, struct name, iface_type##_iface ); \
ULONG ref = InterlockedDecrement( &impl->refcount ); \
if (!ref) free( impl ); \
return ref; \
} \
\
static HRESULT WINAPI name##_Invoke( iface_type *iface, async_type *async, AsyncStatus status ) \
{ \
struct name *impl = CONTAINING_RECORD( iface, struct name, iface_type##_iface ); \
ok( !impl->invoked, "invoked twice\n" ); \
impl->invoked = TRUE; \
if (impl->event) SetEvent( impl->event ); \
return S_OK; \
} \
\
static iface_type##Vtbl name##_vtbl = \
{ \
name##_QueryInterface, \
name##_AddRef, \
name##_Release, \
name##_Invoke, \
}; \
\
static iface_type *name##_create( HANDLE event ) \
{ \
struct name *impl; \
\
if (!(impl = calloc( 1, sizeof(*impl) ))) return NULL; \
impl->iface_type##_iface.lpVtbl = &name##_vtbl; \
impl->event = event; \
impl->refcount = 1; \
\
return &impl->iface_type##_iface; \
} \
\
static DWORD await_##async_type( async_type *async, DWORD timeout ) \
{ \
iface_type *handler; \
HANDLE event; \
HRESULT hr; \
DWORD ret; \
\
event = CreateEventW( NULL, FALSE, FALSE, NULL ); \
ok( !!event, "CreateEventW failed, error %lu\n", GetLastError() ); \
handler = name##_create( event ); \
ok( !!handler, "Failed to create completion handler\n" ); \
hr = async_type##_put_Completed( async, handler ); \
ok( hr == S_OK, "put_Completed returned %#lx\n", hr ); \
ret = WaitForSingleObject( event, timeout ); \
ok( !ret, "WaitForSingleObject returned %#lx\n", ret ); \
CloseHandle( event ); \
iface_type##_Release( handler ); \
\
return ret; \
}
#define check_interface( obj, iid ) check_interface_( __LINE__, obj, iid )
static void check_interface_( unsigned int line, void *obj, const IID *iid )
{
......@@ -51,6 +139,238 @@ static void check_interface_( unsigned int line, void *obj, const IID *iid )
IUnknown_Release( unk );
}
static void load_resource( const WCHAR *name, const WCHAR *type, const WCHAR *filename )
{
DWORD written;
HANDLE file;
HRSRC res;
void *ptr;
file = CreateFileW( filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 );
ok( file != INVALID_HANDLE_VALUE, "failed to create %s, error %lu\n", debugstr_w(filename), GetLastError() );
res = FindResourceW( NULL, name, type );
ok( res != 0, "couldn't find resource\n" );
ptr = LockResource( LoadResource( GetModuleHandleW( NULL ), res ) );
WriteFile( file, ptr, SizeofResource( GetModuleHandleW( NULL ), res ), &written, NULL );
ok( written == SizeofResource( GetModuleHandleW( NULL ), res ), "couldn't write resource\n" );
CloseHandle( file );
}
#define check_async_info( a, b, c ) check_async_info_( __LINE__, a, b, c )
static void check_async_info_( int line, void *async, AsyncStatus expect_status, HRESULT expect_hr )
{
AsyncStatus async_status;
IAsyncInfo *async_info;
HRESULT hr, async_hr;
UINT32 async_id;
hr = IInspectable_QueryInterface( async, &IID_IAsyncInfo, (void **)&async_info );
ok_(__FILE__, line)( hr == S_OK, "QueryInterface returned %#lx\n", hr );
async_id = 0xdeadbeef;
hr = IAsyncInfo_get_Id( async_info, &async_id );
if (expect_status < 4) ok_(__FILE__, line)( hr == S_OK, "get_Id returned %#lx\n", hr );
else ok_(__FILE__, line)( hr == E_ILLEGAL_METHOD_CALL, "get_Id returned %#lx\n", hr );
ok_(__FILE__, line)( !!async_id, "got id %u\n", async_id );
async_status = 0xdeadbeef;
hr = IAsyncInfo_get_Status( async_info, &async_status );
if (expect_status < 4) ok_(__FILE__, line)( hr == S_OK, "get_Status returned %#lx\n", hr );
else ok_(__FILE__, line)( hr == E_ILLEGAL_METHOD_CALL, "get_Status returned %#lx\n", hr );
ok_(__FILE__, line)( async_status == expect_status, "got status %u\n", async_status );
async_hr = 0xdeadbeef;
hr = IAsyncInfo_get_ErrorCode( async_info, &async_hr );
if (expect_status < 4) ok_(__FILE__, line)( hr == S_OK, "get_ErrorCode returned %#lx\n", hr );
else ok_(__FILE__, line)( hr == E_ILLEGAL_METHOD_CALL, "get_ErrorCode returned %#lx\n", hr );
if (expect_status < 4) todo_wine_if(FAILED(expect_hr)) ok_(__FILE__, line)( async_hr == expect_hr, "got error %#lx\n", async_hr );
else ok_(__FILE__, line)( async_hr == E_ILLEGAL_METHOD_CALL, "got error %#lx\n", async_hr );
IAsyncInfo_Release( async_info );
}
DEFINE_ASYNC_COMPLETED_HANDLER( async_deployment_result_handler, IAsyncOperationWithProgressCompletedHandler_DeploymentResult_DeploymentProgress,
IAsyncOperationWithProgress_DeploymentResult_DeploymentProgress )
static HRESULT uri_create( const WCHAR *uri, IUriRuntimeClass **out )
{
static const WCHAR *statics_name = RuntimeClass_Windows_Foundation_Uri;
IUriRuntimeClassFactory *uri_factory;
IActivationFactory *activation;
HSTRING str;
HRESULT hr;
hr = WindowsCreateString( statics_name, wcslen( statics_name ), &str );
ok( hr == S_OK, "got hr %#lx.\n", hr );
hr = RoGetActivationFactory( str, &IID_IActivationFactory, (void **)&activation );
WindowsDeleteString( str );
hr = IActivationFactory_QueryInterface( activation, &IID_IUriRuntimeClassFactory, (void **)&uri_factory );
ok( hr == S_OK, "got hr %#lx.\n", hr );
IActivationFactory_Release( activation );
hr = WindowsCreateString( uri, wcslen( uri ), &str );
ok( hr == S_OK, "got hr %#lx.\n", hr );
IUriRuntimeClassFactory_CreateUri( uri_factory, str, out );
WindowsDeleteString( str );
IUriRuntimeClassFactory_Release( uri_factory );
return hr;
}
static HRESULT test_register_package( IPackageManager *manager, IPackage **out )
{
static const WCHAR app_model_unlock[] = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppModelUnlock";
IAsyncOperationWithProgress_DeploymentResult_DeploymentProgress *operation;
DWORD size, old_value = 0, new_value = 1;
WCHAR temp[MAX_PATH], path[MAX_PATH + 7];
IStorageFolder *storage_folder;
HSTRING str, name, publisher;
IIterable_Package *packages;
IStorageItem *storage_item;
IDeploymentResult *result;
IIterator_Package *iter;
IUriRuntimeClass *uri;
HRESULT hr, async_hr;
IPackage *package;
const WCHAR *buf;
UINT res, len;
HKEY hkey;
GetTempPathW( ARRAY_SIZE(temp), temp );
GetTempFileNameW( temp, L"winetest-winrt", 0, temp );
DeleteFileW( temp );
CreateDirectoryW( temp, NULL );
swprintf( path, MAX_PATH, L"%s\\%s", temp, L"application.exe" );
load_resource( L"application.exe", L"TESTDLL", path );
swprintf( path, MAX_PATH, L"%s\\%s", temp, L"appxmanifest.xml" );
load_resource( L"appxmanifest.xml", (const WCHAR *)RT_RCDATA, path );
swprintf( path, MAX_PATH, L"file://%s\\%s", temp, L"appxmanifest.xml" );
hr = uri_create( path, &uri );
ok( hr == S_OK, "got hr %#lx.\n", hr );
res = RegGetValueW( HKEY_LOCAL_MACHINE, app_model_unlock, L"AllowDevelopmentWithoutDevLicense", RRF_RT_DWORD, NULL,
(BYTE *)&old_value, &size );
if (res) old_value = 0xdeadbeef;
res = RegCreateKeyExW( HKEY_LOCAL_MACHINE, app_model_unlock, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, NULL );
ok( !res, "RegCreateKeyExW failed, res %#x\n", res );
res = RegSetValueExW( hkey, L"AllowDevelopmentWithoutDevLicense", 0, REG_DWORD, (const BYTE *)&new_value, sizeof(new_value) );
ok( !res, "RegCreateKeyExW failed, res %#x\n", res );
/* DeploymentOptions_DevelopmentMode is invalid for AddPackageAsync */
hr = IPackageManager_AddPackageAsync( manager, uri, NULL, DeploymentOptions_DevelopmentMode, &operation );
ok( hr == E_INVALIDARG, "got hr %#lx.\n", hr );
hr = IPackageManager_RegisterPackageAsync( manager, uri, NULL, DeploymentOptions_DevelopmentMode, &operation );
ok( hr == S_OK, "got hr %#lx.\n", hr );
ok( operation != NULL, "got operation %p\n", operation );
IUriRuntimeClass_Release( uri );
res = await_IAsyncOperationWithProgress_DeploymentResult_DeploymentProgress( operation, 5000 );
ok( res == 0, "await_IAsyncOperationWithProgress_DeploymentResult_DeploymentProgress returned %#x\n", res );
hr = IAsyncOperationWithProgress_DeploymentResult_DeploymentProgress_GetResults( operation, &result );
ok( hr == S_OK, "GetResults returned %#lx\n", hr );
IAsyncOperationWithProgress_DeploymentResult_DeploymentProgress_Release( operation );
if (old_value != 0xdeadbeef)
{
res = RegSetValueExW( hkey, L"AllowDevelopmentWithoutDevLicense", 0, REG_DWORD, (const BYTE *)&old_value, sizeof(old_value) );
ok( !res, "RegCreateKeyExW failed, res %#x\n", res );
}
RegCloseKey( hkey );
hr = IDeploymentResult_get_ExtendedErrorCode( result, &async_hr );
ok( hr == S_OK, "get_ExtendedErrorCode returned %#lx\n", hr );
ok( async_hr == S_OK || broken( async_hr == 0x80073cff ) /* 32-bit missing license */ ||
broken( async_hr == 0x80080204 ) /* W8 */ || broken( async_hr == 0x8004264b ) /* w1064v1507 */,
"got error %#lx\n", async_hr );
if (FAILED(async_hr))
{
win_skip("Failed to register package, skipping tests\n");
hr = IDeploymentResult_get_ErrorText( result, &str );
ok( hr == S_OK, "get_ExtendedErrorCode returned %#lx\n", hr );
trace( "got error %s\n", debugstr_hstring(str) );
IDeploymentResult_Release( result );
return async_hr;
}
IDeploymentResult_Release( result );
hr = WindowsCreateString( L"WineTest", wcslen( L"WineTest" ), &name );
ok( hr == S_OK, "got hr %#lx.\n", hr );
hr = WindowsCreateString( L"CN=Wine, O=The Wine Project, C=US", wcslen( L"CN=Wine, O=The Wine Project, C=US" ), &publisher );
ok( hr == S_OK, "got hr %#lx.\n", hr );
hr = IPackageManager_FindPackagesByNamePublisher( manager, name, publisher, &packages );
ok( hr == S_OK, "got hr %#lx.\n", hr );
WindowsDeleteString( name );
WindowsDeleteString( publisher );
hr = IIterable_Package_First( packages, &iter );
ok( hr == S_OK, "got hr %#lx.\n", hr );
IIterable_Package_Release( packages );
hr = IIterator_Package_get_Current( iter, &package );
ok( hr == S_OK, "got hr %#lx.\n", hr );
IIterator_Package_Release( iter );
hr = IPackage_get_InstalledLocation( package, &storage_folder );
ok( hr == S_OK, "got hr %#lx.\n", hr );
hr = IStorageFolder_QueryInterface( storage_folder, &IID_IStorageItem, (void **)&storage_item );
ok( hr == S_OK, "got hr %#lx.\n", hr );
IStorageFolder_Release( storage_folder );
hr = IStorageItem_get_Path( storage_item, &str );
ok( hr == S_OK, "got hr %#lx.\n", hr );
IStorageItem_Release( storage_item );
buf = WindowsGetStringRawBuffer( str, &len );
ok( !wcscmp( temp, buf ), "got path %s.\n", debugstr_hstring( str ) );
WindowsDeleteString( str );
*out = package;
return S_OK;
}
static void test_remove_package( IPackageManager *manager, IPackage *package )
{
IAsyncOperationWithProgress_DeploymentResult_DeploymentProgress *operation;
IDeploymentResult *result;
HRESULT hr, async_hr;
IPackageId *id;
HSTRING name;
UINT res;
hr = IPackage_get_Id( package, &id );
ok( hr == S_OK, "got hr %#lx.\n", hr );
hr = IPackageId_get_FullName( id, &name );
ok( hr == S_OK, "got hr %#lx.\n", hr );
IPackageId_Release( id );
hr = IPackageManager_RemovePackageAsync( manager, name, &operation );
ok( hr == S_OK, "got hr %#lx.\n", hr );
ok( operation != NULL, "got operation %p\n", operation );
res = await_IAsyncOperationWithProgress_DeploymentResult_DeploymentProgress( operation, 5000 );
ok( res == 0, "await_IAsyncOperationWithProgress_DeploymentResult_DeploymentProgress returned %#x\n", res );
check_async_info( operation, Completed, S_OK );
hr = IAsyncOperationWithProgress_DeploymentResult_DeploymentProgress_GetResults( operation, &result );
ok( hr == S_OK, "GetResults returned %#lx\n", hr );
hr = IDeploymentResult_get_ExtendedErrorCode( result, &async_hr );
ok( hr == S_OK, "get_ExtendedErrorCode returned %#lx\n", hr );
ok( async_hr == S_OK, "got error %#lx\n", async_hr );
IDeploymentResult_Release( result );
IAsyncOperationWithProgress_DeploymentResult_DeploymentProgress_Release( operation );
}
static void test_PackageManager(void)
{
static const WCHAR *statics_name = RuntimeClass_Windows_Management_Deployment_PackageManager;
......@@ -120,6 +440,12 @@ static void test_PackageManager(void)
ref = IIterable_Package_Release( packages );
ok( !ref, "got ref %ld.\n", ref );
if (SUCCEEDED(test_register_package( manager, &package )))
{
test_remove_package( manager, package );
IPackage_Release( package );
}
skip_tests:
ref = IPackageManager_Release( manager );
ok( !ref, "got ref %ld.\n", ref );
......
/*
* Copyright 2022 Rémi Bernon for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "windef.h"
/* @makedep: appxmanifest.xml */
appxmanifest.xml RCDATA appxmanifest.xml
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment