Thu, 15 Jan 2015 15:59:08 +0100
Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "FrameworkView.h"
7 #include "MetroUtils.h"
8 #include "nsICommandLineRunner.h"
9 #include "nsNetUtil.h"
10 #include "nsIDOMChromeWindow.h"
11 #include "nsIURI.h"
12 #include "nsPrintfCString.h"
13 #include "mozilla/Services.h"
14 #include <wrl/wrappers/corewrappers.h>
15 #include <shellapi.h>
16 #include <DXGIFormat.h>
17 #include <d2d1_1.h>
18 #include <printpreview.h>
19 #include <D3D10.h>
20 #include "MetroUIUtils.h"
21 #include "nsIStringBundle.h"
23 using namespace mozilla;
24 using namespace ABI::Windows::Foundation;
25 using namespace ABI::Windows::Foundation::Collections;
26 using namespace Microsoft::WRL;
27 using namespace Microsoft::WRL::Wrappers;
29 // Play to contract
30 using namespace ABI::Windows::Media::PlayTo;
32 // Activation contracts
33 using namespace ABI::Windows::ApplicationModel::Activation;
34 using namespace ABI::Windows::ApplicationModel::DataTransfer;
35 using namespace ABI::Windows::ApplicationModel::Search;
37 // Settings contract
38 using namespace ABI::Windows::UI::ApplicationSettings;
39 using namespace ABI::Windows::UI::Popups;
41 // Print contract
42 using namespace ABI::Windows::Graphics::Printing;
44 namespace mozilla {
45 namespace widget {
46 namespace winrt {
48 extern nsTArray<nsString>* sSettingsArray;
50 void
51 FrameworkView::SearchActivated(ComPtr<ISearchActivatedEventArgs>& aArgs, bool aStartup)
52 {
53 if (!aArgs)
54 return;
56 HString data;
57 AssertHRESULT(aArgs->get_QueryText(data.GetAddressOf()));
58 if (WindowsIsStringEmpty(data.Get()))
59 return;
61 unsigned int length;
62 WinUtils::LogW(L"SearchActivated text=%s", data.GetRawBuffer(&length));
63 if (aStartup) {
64 WindowsDuplicateString(data.Get(), &sActivationURI);
65 } else {
66 PerformURILoadOrSearch(data);
67 }
68 }
70 void
71 FrameworkView::FileActivated(ComPtr<IFileActivatedEventArgs>& aArgs, bool aStartup)
72 {
73 if (!aArgs)
74 return;
76 ComPtr<IVectorView<ABI::Windows::Storage::IStorageItem*>> list;
77 AssertHRESULT(aArgs->get_Files(list.GetAddressOf()));
78 ComPtr<ABI::Windows::Storage::IStorageItem> item;
79 AssertHRESULT(list->GetAt(0, item.GetAddressOf()));
80 HString filePath;
81 AssertHRESULT(item->get_Path(filePath.GetAddressOf()));
83 if (aStartup) {
84 WindowsDuplicateString(filePath.Get(), &sActivationURI);
85 } else {
86 PerformURILoad(filePath);
87 }
88 }
90 void
91 FrameworkView::LaunchActivated(ComPtr<ILaunchActivatedEventArgs>& aArgs, bool aStartup)
92 {
93 if (!aArgs)
94 return;
95 HString data;
96 AssertHRESULT(aArgs->get_Arguments(data.GetAddressOf()));
97 if (WindowsIsStringEmpty(data.Get()))
98 return;
100 // If we're being launched from a secondary tile then we have a 2nd command line param of -url
101 // and a third of the secondary tile. We want it in sActivationURI so that browser.js will
102 // load it in without showing the start UI.
103 int argc;
104 unsigned int length;
105 LPWSTR* argv = CommandLineToArgvW(data.GetRawBuffer(&length), &argc);
106 if (aStartup && argc == 2 && !wcsicmp(argv[0], L"-url")) {
107 WindowsCreateString(argv[1], wcslen(argv[1]), &sActivationURI);
108 } else {
109 // Some other command line or this is not a startup.
110 // If it is startup we process it later when XPCOM is initialilzed.
111 mActivationCommandLine = data.GetRawBuffer(&length);
112 if (!aStartup) {
113 ProcessLaunchArguments();
114 }
115 }
116 }
118 void
119 FrameworkView::ProcessLaunchArguments()
120 {
121 if (!mActivationCommandLine.Length())
122 return;
124 int argc;
125 LPWSTR* argv = CommandLineToArgvW(mActivationCommandLine.BeginReading(), &argc);
126 nsCOMPtr<nsICommandLineRunner> cmdLine =
127 (do_CreateInstance("@mozilla.org/toolkit/command-line;1"));
128 if (!cmdLine) {
129 NS_WARNING("Unable to instantiate command line runner.");
130 return;
131 }
133 LPSTR *argvUTF8 = new LPSTR[argc];
134 for (int i = 0; i < argc; ++i) {
135 NS_ConvertUTF16toUTF8 arg(argv[i]);
136 argvUTF8[i] = new char[arg.Length() + 1];
137 strcpy(argvUTF8[i], const_cast<char *>(arg.BeginReading()));
138 WinUtils::LogW(L"Launch arg[%d]: '%s'", i, argv[i]);
139 }
141 nsresult rv = cmdLine->Init(argc,
142 argvUTF8,
143 nullptr,
144 nsICommandLine::STATE_REMOTE_EXPLICIT);
145 if (NS_SUCCEEDED(rv)) {
146 cmdLine->Run();
147 } else {
148 NS_WARNING("cmdLine->Init failed.");
149 }
151 for (int i = 0; i < argc; ++i) {
152 delete[] argvUTF8[i];
153 }
154 delete[] argvUTF8;
155 }
157 void
158 FrameworkView::ProcessActivationArgs(IActivatedEventArgs* aArgs, bool aStartup)
159 {
160 ActivationKind kind;
161 if (!aArgs || FAILED(aArgs->get_Kind(&kind)))
162 return;
163 ComPtr<IActivatedEventArgs> args(aArgs);
164 if (kind == ActivationKind::ActivationKind_Protocol) {
165 WinUtils::Log("Activation argument kind: Protocol");
166 ComPtr<IProtocolActivatedEventArgs> protoArgs;
167 AssertHRESULT(args.As(&protoArgs));
168 ComPtr<IUriRuntimeClass> uri;
169 AssertHRESULT(protoArgs->get_Uri(uri.GetAddressOf()));
170 if (!uri)
171 return;
173 HString data;
174 AssertHRESULT(uri->get_AbsoluteUri(data.GetAddressOf()));
175 if (WindowsIsStringEmpty(data.Get()))
176 return;
178 if (aStartup) {
179 WindowsDuplicateString(data.Get(), &sActivationURI);
180 } else {
181 PerformURILoad(data);
182 }
183 } else if (kind == ActivationKind::ActivationKind_Search) {
184 WinUtils::Log("Activation argument kind: Search");
185 ComPtr<ISearchActivatedEventArgs> searchArgs;
186 args.As(&searchArgs);
187 SearchActivated(searchArgs, aStartup);
188 } else if (kind == ActivationKind::ActivationKind_File) {
189 WinUtils::Log("Activation argument kind: File");
190 ComPtr<IFileActivatedEventArgs> fileArgs;
191 args.As(&fileArgs);
192 FileActivated(fileArgs, aStartup);
193 } else if (kind == ActivationKind::ActivationKind_Launch) {
194 WinUtils::Log("Activation argument kind: Launch");
195 ComPtr<ILaunchActivatedEventArgs> launchArgs;
196 args.As(&launchArgs);
197 LaunchActivated(launchArgs, aStartup);
198 }
199 }
201 void
202 FrameworkView::SetupContracts()
203 {
204 LogFunction();
205 HRESULT hr;
207 // Add support for the share charm to indicate that we share data to other apps
208 ComPtr<IDataTransferManagerStatics> transStatics;
209 hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_ApplicationModel_DataTransfer_DataTransferManager).Get(),
210 transStatics.GetAddressOf());
211 AssertHRESULT(hr);
212 ComPtr<IDataTransferManager> trans;
213 AssertHRESULT(transStatics->GetForCurrentView(trans.GetAddressOf()));
214 trans->add_DataRequested(Callback<__FITypedEventHandler_2_Windows__CApplicationModel__CDataTransfer__CDataTransferManager_Windows__CApplicationModel__CDataTransfer__CDataRequestedEventArgs_t>(
215 this, &FrameworkView::OnDataShareRequested).Get(), &mDataTransferRequested);
217 // Add support for the search charm to indicate that you can search using our app.
218 ComPtr<ISearchPaneStatics> searchStatics;
219 hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_ApplicationModel_Search_SearchPane).Get(),
220 searchStatics.GetAddressOf());
221 AssertHRESULT(hr);
222 ComPtr<ISearchPane> searchPane;
223 AssertHRESULT(searchStatics->GetForCurrentView(searchPane.GetAddressOf()));
224 searchPane->add_QuerySubmitted(Callback<__FITypedEventHandler_2_Windows__CApplicationModel__CSearch__CSearchPane_Windows__CApplicationModel__CSearch__CSearchPaneQuerySubmittedEventArgs_t>(
225 this, &FrameworkView::OnSearchQuerySubmitted).Get(), &mSearchQuerySubmitted);
227 // Add support for the devices play to charm
228 ComPtr<IPlayToManagerStatics> playToStatics;
229 hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_Media_PlayTo_PlayToManager).Get(),
230 playToStatics.GetAddressOf());
231 AssertHRESULT(hr);
232 ComPtr<IPlayToManager> playTo;
233 AssertHRESULT(playToStatics->GetForCurrentView(playTo.GetAddressOf()));
234 playTo->add_SourceRequested(Callback<__FITypedEventHandler_2_Windows__CMedia__CPlayTo__CPlayToManager_Windows__CMedia__CPlayTo__CPlayToSourceRequestedEventArgs_t>(
235 this, &FrameworkView::OnPlayToSourceRequested).Get(), &mPlayToRequested);
237 // Add support for the settings charm
238 ComPtr<ISettingsPaneStatics> settingsPaneStatics;
239 hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_ApplicationSettings_SettingsPane).Get(),
240 settingsPaneStatics.GetAddressOf());
241 AssertHRESULT(hr);
242 ComPtr<ISettingsPane> settingsPane;
243 AssertHRESULT(settingsPaneStatics->GetForCurrentView(settingsPane.GetAddressOf()));
244 settingsPane->add_CommandsRequested(Callback<__FITypedEventHandler_2_Windows__CUI__CApplicationSettings__CSettingsPane_Windows__CUI__CApplicationSettings__CSettingsPaneCommandsRequestedEventArgs_t>(
245 this, &FrameworkView::OnSettingsCommandsRequested).Get(), &mSettingsPane);
247 // Add support for the settings print charm
248 ComPtr<IPrintManagerStatic> printStatics;
249 hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_Graphics_Printing_PrintManager).Get(),
250 printStatics.GetAddressOf());
251 AssertHRESULT(hr);
252 ComPtr<IPrintManager> printManager;
253 AssertHRESULT(printStatics->GetForCurrentView(printManager.GetAddressOf()));
254 printManager->add_PrintTaskRequested(Callback<__FITypedEventHandler_2_Windows__CGraphics__CPrinting__CPrintManager_Windows__CGraphics__CPrinting__CPrintTaskRequestedEventArgs_t>(
255 this, &FrameworkView::OnPrintTaskRequested).Get(), &mPrintManager);
256 }
258 void
259 FrameworkView::PerformURILoad(HString& aURI)
260 {
261 LogFunction();
263 unsigned int length;
264 WinUtils::LogW(L"PerformURILoad uri=%s", aURI.GetRawBuffer(&length));
266 nsCOMPtr<nsICommandLineRunner> cmdLine =
267 (do_CreateInstance("@mozilla.org/toolkit/command-line;1"));
268 if (!cmdLine) {
269 NS_WARNING("Unable to instantiate command line runner.");
270 return;
271 }
273 nsAutoCString utf8data(NS_ConvertUTF16toUTF8(aURI.GetRawBuffer(&length)));
275 // NB: The first argument gets stripped by nsICommandLineRunner::Init,
276 // so it doesn't matter what we pass as the first argument, but we
277 // have to pass something.
278 const char *argv[] = { "", // This argument gets stripped
279 "-url",
280 utf8data.BeginReading() };
281 nsresult rv = cmdLine->Init(ArrayLength(argv),
282 const_cast<char **>(argv), nullptr,
283 nsICommandLine::STATE_REMOTE_EXPLICIT);
284 if (NS_FAILED(rv)) {
285 NS_WARNING("cmdLine->Init failed.");
286 return;
287 }
288 cmdLine->Run();
289 }
291 void
292 FrameworkView::PerformSearch(HString& aQuery)
293 {
294 LogFunction();
296 nsCOMPtr<nsICommandLineRunner> cmdLine =
297 (do_CreateInstance("@mozilla.org/toolkit/command-line;1"));
298 if (!cmdLine) {
299 NS_WARNING("Unable to instantiate command line runner.");
300 return;
301 }
303 nsAutoCString parameter;
304 parameter.AppendLiteral("\"");
305 unsigned int length;
306 parameter.Append(NS_ConvertUTF16toUTF8(aQuery.GetRawBuffer(&length)));
307 parameter.AppendLiteral("\"");
309 // NB: The first argument gets stripped by nsICommandLineRunner::Init,
310 // so it doesn't matter what we pass as the first argument, but we
311 // have to pass something.
312 const char *argv[] = { "", // This argument gets stripped
313 "-search",
314 parameter.BeginReading() };
315 nsresult rv = cmdLine->Init(ArrayLength(argv),
316 const_cast<char **>(argv), nullptr,
317 nsICommandLine::STATE_REMOTE_EXPLICIT);
318 if (NS_FAILED(rv)) {
319 NS_WARNING("cmdLine->Init failed.");
320 return;
321 }
322 cmdLine->Run();
323 }
325 void
326 FrameworkView::PerformURILoadOrSearch(HString& aString)
327 {
328 LogFunction();
330 if (WindowsIsStringEmpty(aString.Get())) {
331 WinUtils::Log("Emptry string passed to PerformURILoadOrSearch");
332 return;
333 }
335 // If we have a URI then devert to load the URI directly
336 ComPtr<IUriRuntimeClass> uri;
337 MetroUtils::CreateUri(aString.Get(), uri);
338 if (uri) {
339 PerformURILoad(aString);
340 } else {
341 PerformSearch(aString);
342 }
343 }
345 HRESULT
346 FrameworkView::OnDataShareRequested(IDataTransferManager* aDTM,
347 IDataRequestedEventArgs* aArg)
348 {
349 // Only share pages that contain a title and a URI
350 nsCOMPtr<nsIMetroUIUtils> metroUIUtils = do_CreateInstance("@mozilla.org/metro-ui-utils;1");
351 if (!metroUIUtils)
352 return E_FAIL;
354 nsString url, title;
355 nsresult rv = metroUIUtils->GetCurrentPageURI(url);
356 nsresult rv2 = metroUIUtils->GetCurrentPageTitle(title);
357 if (NS_FAILED(rv) || NS_FAILED(rv2)) {
358 return E_FAIL;
359 }
361 // Get the package to share
362 HRESULT hr;
363 ComPtr<IDataRequest> request;
364 AssertRetHRESULT(hr = aArg->get_Request(request.GetAddressOf()), hr);
365 ComPtr<IDataPackage> dataPackage;
366 AssertRetHRESULT(hr = request->get_Data(dataPackage.GetAddressOf()), hr);
367 ComPtr<IDataPackagePropertySet> props;
368 AssertRetHRESULT(hr = dataPackage->get_Properties(props.GetAddressOf()), hr);
370 // Only add a URI to the package when there is no selected content.
371 // This is because most programs treat URIs as highest priority to generate
372 // their own preview, but we only want the selected content to show up.
373 bool hasSelectedContent = false;
374 metroUIUtils->GetHasSelectedContent(&hasSelectedContent);
375 if (!hasSelectedContent) {
376 ComPtr<IUriRuntimeClass> uri;
377 AssertRetHRESULT(hr = MetroUtils::CreateUri(HStringReference(url.BeginReading()).Get(), uri), hr);
379 // If there is no selection, then we don't support sharing for sites that
380 // are not HTTP, HTTPS, FTP, and FILE.
381 HString schemeHString;
382 uri->get_SchemeName(schemeHString.GetAddressOf());
383 unsigned int length;
384 LPCWSTR scheme = schemeHString.GetRawBuffer(&length);
385 if (!scheme || wcscmp(scheme, L"http") && wcscmp(scheme, L"https") &&
386 wcscmp(scheme, L"ftp") && wcscmp(scheme, L"file")) {
387 return S_OK;
388 }
390 AssertRetHRESULT(hr = dataPackage->SetUri(uri.Get()), hr);
391 }
393 // Add whatever content metroUIUtils wants us to for the text sharing
394 nsString shareText;
395 if (NS_SUCCEEDED(metroUIUtils->GetShareText(shareText)) && shareText.Length()) {
396 AssertRetHRESULT(hr = dataPackage->SetText(HStringReference(shareText.BeginReading()).Get()) ,hr);
397 }
399 // Add whatever content metroUIUtils wants us to for the HTML sharing
400 nsString shareHTML;
401 if (NS_SUCCEEDED(metroUIUtils->GetShareHTML(shareHTML)) && shareHTML.Length()) {
402 // The sharing format needs some special headers, so pass it through Windows
403 ComPtr<IHtmlFormatHelperStatics> htmlFormatHelper;
404 hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_ApplicationModel_DataTransfer_HtmlFormatHelper).Get(),
405 htmlFormatHelper.GetAddressOf());
406 AssertRetHRESULT(hr, hr);
407 HSTRING fixedHTML;
408 htmlFormatHelper->CreateHtmlFormat(HStringReference(shareHTML.BeginReading()).Get(), &fixedHTML);
410 // And now add the fixed HTML to the data package
411 AssertRetHRESULT(hr = dataPackage->SetHtmlFormat(fixedHTML), hr);
412 }
414 // Obtain the brand name
415 nsCOMPtr<nsIStringBundleService> bundleService =
416 do_GetService(NS_STRINGBUNDLE_CONTRACTID);
417 NS_ENSURE_TRUE(bundleService, E_FAIL);
418 nsCOMPtr<nsIStringBundle> brandBundle;
419 nsString brandName;
420 bundleService->CreateBundle("chrome://branding/locale/brand.properties",
421 getter_AddRefs(brandBundle));
422 NS_ENSURE_TRUE(brandBundle, E_FAIL);
423 if(brandBundle) {
424 brandBundle->GetStringFromName(MOZ_UTF16("brandFullName"),
425 getter_Copies(brandName));
426 }
428 // Set these properties at the end. Otherwise users can get a
429 // "There was a problem with the data package" error when there
430 // is simply nothing to share.
431 props->put_ApplicationName(HStringReference(brandName.BeginReading()).Get());
432 if (title.Length()) {
433 props->put_Title(HStringReference(title.BeginReading()).Get());
434 } else {
435 props->put_Title(HStringReference(brandName.BeginReading()).Get());
436 }
437 props->put_Description(HStringReference(url.BeginReading()).Get());
439 return S_OK;
440 }
442 HRESULT
443 FrameworkView::OnSearchQuerySubmitted(ISearchPane* aPane,
444 ISearchPaneQuerySubmittedEventArgs* aArgs)
445 {
446 LogFunction();
447 HString aQuery;
448 aArgs->get_QueryText(aQuery.GetAddressOf());
449 PerformURILoadOrSearch(aQuery);
450 return S_OK;
451 }
453 HRESULT
454 FrameworkView::OnSettingsCommandInvoked(IUICommand* aCommand)
455 {
456 LogFunction();
457 HRESULT hr;
458 uint32_t id;
459 ComPtr<IPropertyValue> prop;
460 AssertRetHRESULT(hr = aCommand->get_Id((IInspectable**)prop.GetAddressOf()), hr);
461 AssertRetHRESULT(hr = prop->GetUInt32(&id), hr);
463 nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
464 if (obs) {
465 NS_ConvertASCIItoUTF16 idStr(nsPrintfCString("%lu", id));
466 obs->NotifyObservers(nullptr, "metro-settings-entry-selected", idStr.BeginReading());
467 }
469 return S_OK;
470 }
472 void
473 FrameworkView::AddSetting(ISettingsPaneCommandsRequestedEventArgs* aArgs,
474 uint32_t aId, HString& aSettingName)
475 {
476 HRESULT hr;
478 ComPtr<ABI::Windows::UI::ApplicationSettings::ISettingsPaneCommandsRequest> request;
479 AssertHRESULT(aArgs->get_Request(request.GetAddressOf()));
481 // ApplicationCommands - vector that holds SettingsCommand to be invoked
482 ComPtr<IVector<ABI::Windows::UI::ApplicationSettings::SettingsCommand*>> list;
483 AssertHRESULT(request->get_ApplicationCommands(list.GetAddressOf()));
485 ComPtr<IUICommand> command;
486 ComPtr<ISettingsCommandFactory> factory;
487 hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_ApplicationSettings_SettingsCommand).Get(),
488 factory.GetAddressOf());
489 AssertHRESULT(hr);
491 // Create the IInspectable string property that identifies this command
492 ComPtr<IInspectable> prop;
493 ComPtr<IPropertyValueStatics> propStatics;
494 hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_Foundation_PropertyValue).Get(),
495 propStatics.GetAddressOf());
496 AssertHRESULT(hr);
497 hr = propStatics->CreateUInt32(aId, prop.GetAddressOf());
498 AssertHRESULT(hr);
500 // Create the command
501 hr = factory->CreateSettingsCommand(prop.Get(), aSettingName.Get(),
502 Callback<ABI::Windows::UI::Popups::IUICommandInvokedHandler>(
503 this, &FrameworkView::OnSettingsCommandInvoked).Get(), command.GetAddressOf());
504 AssertHRESULT(hr);
506 // Add it to the list
507 hr = list->Append(command.Get());
508 AssertHRESULT(hr);
509 }
511 HRESULT
512 FrameworkView::OnSettingsCommandsRequested(ISettingsPane* aPane,
513 ISettingsPaneCommandsRequestedEventArgs* aArgs)
514 {
515 if (!sSettingsArray)
516 return E_FAIL;
517 if (!sSettingsArray->Length())
518 return S_OK;
519 for (uint32_t i = 0; i < sSettingsArray->Length(); i++) {
520 HString label;
521 label.Set(sSettingsArray->ElementAt(i).BeginReading());
522 AddSetting(aArgs, i, label);
523 }
524 return S_OK;
525 }
527 HRESULT
528 FrameworkView::OnPlayToSourceRequested(IPlayToManager* aPlayToManager,
529 IPlayToSourceRequestedEventArgs* aArgs)
530 {
531 // TODO: Implement PlayTo, find the element on the page and then do something similar to this:
532 // PlayToReceiver::Dispatcher.Helper.BeginInvoke(
533 // mMediaElement = ref new Windows::UI::Xaml::Controls::MediaElement();
534 // mMediaElement->Source = ref new Uri("http://www.youtube.com/watch?v=2U0NFgoNI7s");
535 // aArgs->SourceRequest->SetSource(mMediaElement->PlayToSource);
536 return S_OK;
537 }
539 HRESULT
540 FrameworkView::OnPrintTaskSourceRequested(IPrintTaskSourceRequestedArgs* aArgs)
541 {
542 return S_OK;
543 }
545 HRESULT
546 FrameworkView::OnPrintTaskRequested(IPrintManager* aPrintManager,
547 IPrintTaskRequestedEventArgs* aArgs)
548 {
549 return S_OK;
550 }
552 void
553 FrameworkView::CreatePrintControl(IPrintDocumentPackageTarget* docPackageTarget,
554 D2D1_PRINT_CONTROL_PROPERTIES* printControlProperties)
555 {
556 }
558 HRESULT
559 FrameworkView::ClosePrintControl()
560 {
561 return S_OK;
562 }
564 // Print out one page, with the given print ticket.
565 // This sample has only one page and we ignore pageNumber below.
566 void FrameworkView::PrintPage(uint32_t pageNumber,
567 D2D1_RECT_F imageableArea,
568 D2D1_SIZE_F pageSize,
569 IStream* pagePrintTicketStream)
570 {
571 }
573 } } }