Bug Summary

File:/boot/home/haiku/haiku/src/kits/interface/PrintJob.cpp
Location:line 278, column 3
Description:Use of memory after it is freed

Annotated Source Code

1/*
2 * Copyright 2001-2009, Haiku.
3 * Distributed under the terms of the MIT license.
4 *
5 * Authors:
6 * I.R. Adema
7 * Stefano Ceccherini (burton666@libero.it)
8 * Michael Pfeiffer
9 * julun <host.haiku@gmx.de>
10 */
11
12
13#include <PrintJob.h>
14
15#include <stdio.h>
16#include <stdlib.h>
17#include <string.h>
18
19#include <Alert.h>
20#include <Application.h>
21#include <Button.h>
22#include <Debug.h>
23#include <Entry.h>
24#include <File.h>
25#include <FindDirectory.h>
26#include <Messenger.h>
27#include <NodeInfo.h>
28#include <OS.h>
29#include <Path.h>
30#include <Region.h>
31#include <Roster.h>
32#include <SystemCatalog.h>
33#include <View.h>
34
35#include <pr_server.h>
36#include <ViewPrivate.h>
37
38using BPrivate::gSystemCatalog;
39
40#undef B_TRANSLATION_CONTEXT"PrintJob"
41#define B_TRANSLATION_CONTEXT"PrintJob" "PrintJob"
42
43#undef B_TRANSLATE
44#define B_TRANSLATE(str)gSystemCatalog.GetString((str), "PrintJob") \
45 gSystemCatalog.GetString(B_TRANSLATE_MARK(str)(str), "PrintJob")
46
47
48/*! Summary of spool file:
49
50 |-----------------------------------|
51 | print_file_header |
52 |-----------------------------------|
53 | BMessage print_job_settings |
54 |-----------------------------------|
55 | |
56 | ********** (first page) ********* |
57 | * * |
58 | * _page_header_ * |
59 | * ----------------------------- * |
60 | * |---------------------------| * |
61 | * | BPoint where | * |
62 | * | BRect bounds | * |
63 | * | BPicture pic | * |
64 | * |---------------------------| * |
65 | * |---------------------------| * |
66 | * | BPoint where | * |
67 | * | BRect bounds | * |
68 | * | BPicture pic | * |
69 | * |---------------------------| * |
70 | ********************************* |
71 | |
72 | ********* (second page) ********* |
73 | * * |
74 | * _page_header_ * |
75 | * ----------------------------- * |
76 | * |---------------------------| * |
77 | * | BPoint where | * |
78 | * | BRect bounds | * |
79 | * | BPicture pic | * |
80 | * |---------------------------| * |
81 | ********************************* |
82 |-----------------------------------|
83
84 BeOS R5 print_file_header.version is 1 << 16
85 BeOS R5 print_file_header.first_page is -1
86
87 each page can consist of a collection of picture structures
88 remaining pages start at _page_header_.next_page of previous _page_header_
89
90 See also: "How to Write a BeOS R5 Printer Driver" for description of spool
91 file format: http://haiku-os.org/documents/dev/how_to_write_a_printer_driver
92*/
93
94
95struct _page_header_ {
96 int32 number_of_pictures;
97 off_t next_page;
98 int32 reserved[10];
99};
100
101
102static void
103ShowError(const char* message)
104{
105 BAlert* alert = new BAlert(B_TRANSLATE("Error")gSystemCatalog.GetString(("Error"), "PrintJob"), message, B_TRANSLATE("OK")gSystemCatalog.GetString(("OK"), "PrintJob"));
106 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
107 alert->Go();
108}
109
110
111// #pragma mark -- PrintServerMessenger
112
113
114namespace BPrivate {
115
116
117class PrintServerMessenger {
118public:
119 PrintServerMessenger(uint32 what, BMessage* input);
120 ~PrintServerMessenger();
121
122 BMessage* Request();
123 status_t SendRequest();
124
125 void SetResult(BMessage* result);
126 BMessage* Result() const { return fResult; }
127
128 static status_t GetPrintServerMessenger(BMessenger& messenger);
129
130private:
131 void RejectUserInput();
132 void AllowUserInput();
133 void DeleteSemaphore();
134 static status_t MessengerThread(void* data);
135
136 uint32 fWhat;
137 BMessage* fInput;
138 BMessage* fRequest;
139 BMessage* fResult;
140 sem_id fThreadCompleted;
141 BAlert* fHiddenApplicationModalWindow;
142};
143
144
145} // namespace BPrivate
146
147
148using namespace BPrivate;
149
150
151// #pragma mark -- BPrintJob
152
153
154BPrintJob::BPrintJob(const char* jobName)
155 :
156 fPrintJobName(NULL__null),
157 fSpoolFile(NULL__null),
158 fError(B_NO_INIT((-2147483647 - 1) + 13)),
159 fSetupMessage(NULL__null),
160 fDefaultSetupMessage(NULL__null),
161 fAbort(0),
162 fCurrentPageHeader(NULL__null)
163{
164 memset(&fSpoolFileHeader, 0, sizeof(print_file_header));
165
166 if (jobName != NULL__null && jobName[0])
167 fPrintJobName = strdup(jobName);
168
169 fCurrentPageHeader = new _page_header_;
170 if (fCurrentPageHeader != NULL__null)
171 memset(fCurrentPageHeader, 0, sizeof(_page_header_));
172}
173
174
175BPrintJob::~BPrintJob()
176{
177 CancelJob();
178
179 free(fPrintJobName);
180 delete fSetupMessage;
181 delete fDefaultSetupMessage;
182 delete fCurrentPageHeader;
183}
184
185
186status_t
187BPrintJob::ConfigPage()
188{
189 PrintServerMessenger messenger(PSRV_SHOW_PAGE_SETUP'pgst', fSetupMessage);
190 status_t status = messenger.SendRequest();
191 if (status != B_OK((int)0))
192 return status;
193
194 delete fSetupMessage;
195 fSetupMessage = messenger.Result();
196 _HandlePageSetup(fSetupMessage);
197
198 return B_OK((int)0);
199}
200
201
202status_t
203BPrintJob::ConfigJob()
204{
205 PrintServerMessenger messenger(PSRV_SHOW_PRINT_SETUP'ppst', fSetupMessage);
206 status_t status = messenger.SendRequest();
207 if (status != B_OK((int)0))
208 return status;
209
210 delete fSetupMessage;
211 fSetupMessage = messenger.Result();
212 if (!_HandlePrintSetup(fSetupMessage))
213 return B_ERROR(-1);
214
215 fError = B_OK((int)0);
216 return B_OK((int)0);
217}
218
219
220void
221BPrintJob::BeginJob()
222{
223 fError = B_ERROR(-1);
224
225 // can not start a new job until it has been commited or cancelled
226 if (fSpoolFile != NULL__null || fCurrentPageHeader == NULL__null)
1
Taking false branch
227 return;
228
229 // TODO show alert, setup message is required
230 if (fSetupMessage == NULL__null)
2
Taking false branch
231 return;
232
233 // create spool file
234 BPath path;
235 status_t status = find_directory(B_USER_PRINTERS_DIRECTORY, &path);
236 if (status != B_OK((int)0))
3
Assuming 'status' is equal to 0
4
Taking false branch
237 return;
238
239 char *printer = _GetCurrentPrinterName();
5
Calling 'BPrintJob::_GetCurrentPrinterName'
10
Returned allocated memory
240 if (printer == NULL__null)
11
Taking false branch
241 return;
242
243 path.Append(printer);
244 free(printer);
12
Memory is released
245
246 char mangledName[B_FILE_NAME_LENGTH(256)];
247 _GetMangledName(mangledName, B_FILE_NAME_LENGTH(256));
248
249 path.Append(mangledName);
250 if (path.InitCheck() != B_OK((int)0))
13
Taking false branch
251 return;
252
253 // TODO: fSpoolFileName should store the name only (not path which can be
254 // 1024 bytes long)
255 strlcpy(fSpoolFileName, path.Path(), sizeof(fSpoolFileName));
256 fSpoolFile = new BFile(fSpoolFileName, B_READ_WRITE0x0002 | B_CREATE_FILE0x0200);
257
258 if (fSpoolFile->InitCheck() != B_OK((int)0)) {
14
Taking false branch
259 CancelJob();
260 return;
261 }
262
263 // add print_file_header
264 // page_count is updated in CommitJob()
265 // on BeOS R5 the offset to the first page was always -1
266 fSpoolFileHeader.version = 1 << 16;
267 fSpoolFileHeader.page_count = 0;
268 fSpoolFileHeader.first_page = (off_t)-1;
269
270 if (fSpoolFile->Write(&fSpoolFileHeader, sizeof(print_file_header))
15
Taking false branch
271 != sizeof(print_file_header)) {
272 CancelJob();
273 return;
274 }
275
276 // add printer settings message
277 if (!fSetupMessage->HasString(PSRV_FIELD_CURRENT_PRINTER"current_printer"))
16
Taking true branch
278 fSetupMessage->AddString(PSRV_FIELD_CURRENT_PRINTER"current_printer", printer);
17
Use of memory after it is freed
279
280 _AddSetupSpec();
281 _NewPage();
282
283 // state variables
284 fAbort = 0;
285 fError = B_OK((int)0);
286}
287
288
289void
290BPrintJob::CommitJob()
291{
292 if (fSpoolFile == NULL__null)
293 return;
294
295 if (fSpoolFileHeader.page_count == 0) {
296 ShowError(B_TRANSLATE("No Pages to print!")gSystemCatalog.GetString(("No Pages to print!"), "PrintJob"));
297 CancelJob();
298 return;
299 }
300
301 // update spool file
302 _EndLastPage();
303
304 // write spool file header
305 fSpoolFile->Seek(0, SEEK_SET0);
306 fSpoolFile->Write(&fSpoolFileHeader, sizeof(print_file_header));
307
308 // set file attributes
309 app_info appInfo;
310 be_app->GetAppInfo(&appInfo);
311 const char* printerName = "";
312 fSetupMessage->FindString(PSRV_FIELD_CURRENT_PRINTER"current_printer", &printerName);
313
314 BNodeInfo info(fSpoolFile);
315 info.SetType(PSRV_SPOOL_FILETYPE"application/x-vnd.Be.printer-spool");
316
317 fSpoolFile->WriteAttr(PSRV_SPOOL_ATTR_PAGECOUNT"_spool/Page Count", B_INT32_TYPE, 0,
318 &fSpoolFileHeader.page_count, sizeof(int32));
319 fSpoolFile->WriteAttr(PSRV_SPOOL_ATTR_DESCRIPTION"_spool/Description", B_STRING_TYPE, 0,
320 fPrintJobName, strlen(fPrintJobName) + 1);
321 fSpoolFile->WriteAttr(PSRV_SPOOL_ATTR_PRINTER"_spool/Printer", B_STRING_TYPE, 0,
322 printerName, strlen(printerName) + 1);
323 fSpoolFile->WriteAttr(PSRV_SPOOL_ATTR_STATUS"_spool/Status", B_STRING_TYPE, 0,
324 PSRV_JOB_STATUS_WAITING"Waiting", strlen(PSRV_JOB_STATUS_WAITING"Waiting") + 1);
325 fSpoolFile->WriteAttr(PSRV_SPOOL_ATTR_MIMETYPE"_spool/MimeType", B_STRING_TYPE, 0,
326 appInfo.signature, strlen(appInfo.signature) + 1);
327
328 delete fSpoolFile;
329 fSpoolFile = NULL__null;
330 fError = B_ERROR(-1);
331
332 // notify print server
333 BMessenger printServer;
334 if (PrintServerMessenger::GetPrintServerMessenger(printServer) != B_OK((int)0))
335 return;
336
337 BMessage request(PSRV_PRINT_SPOOLED_JOB'psns');
338 request.AddString("JobName", fPrintJobName);
339 request.AddString("Spool File", fSpoolFileName);
340
341 BMessage reply;
342 printServer.SendMessage(&request, &reply);
343}
344
345
346void
347BPrintJob::CancelJob()
348{
349 if (fSpoolFile == NULL__null)
350 return;
351
352 fAbort = 1;
353 BEntry(fSpoolFileName).Remove();
354 delete fSpoolFile;
355 fSpoolFile = NULL__null;
356}
357
358
359void
360BPrintJob::SpoolPage()
361{
362 if (fSpoolFile == NULL__null)
363 return;
364
365 if (fCurrentPageHeader->number_of_pictures == 0)
366 return;
367
368 fSpoolFileHeader.page_count++;
369 fSpoolFile->Seek(0, SEEK_END2);
370 if (fCurrentPageHeaderOffset) {
371 // update last written page_header
372 fCurrentPageHeader->next_page = fSpoolFile->Position();
373 fSpoolFile->Seek(fCurrentPageHeaderOffset, SEEK_SET0);
374 fSpoolFile->Write(fCurrentPageHeader, sizeof(_page_header_));
375 fSpoolFile->Seek(fCurrentPageHeader->next_page, SEEK_SET0);
376 }
377
378 _NewPage();
379}
380
381
382bool
383BPrintJob::CanContinue()
384{
385 // Check if our local error storage is still B_OK
386 return fError == B_OK((int)0) && !fAbort;
387}
388
389
390void
391BPrintJob::DrawView(BView* view, BRect rect, BPoint where)
392{
393 if (fSpoolFile == NULL__null)
394 return;
395
396 if (view == NULL__null)
397 return;
398
399 if (view->LockLooper()) {
400 BPicture picture;
401 _RecurseView(view, B_ORIGIN - rect.LeftTop(), &picture, rect);
402 _AddPicture(picture, rect, where);
403 view->UnlockLooper();
404 }
405}
406
407
408BMessage*
409BPrintJob::Settings()
410{
411 if (fSetupMessage == NULL__null)
412 return NULL__null;
413
414 return new BMessage(*fSetupMessage);
415}
416
417
418void
419BPrintJob::SetSettings(BMessage* message)
420{
421 if (message != NULL__null)
422 _HandlePrintSetup(message);
423
424 delete fSetupMessage;
425 fSetupMessage = message;
426}
427
428
429bool
430BPrintJob::IsSettingsMessageValid(BMessage* message) const
431{
432 char* printerName = _GetCurrentPrinterName();
433 if (printerName == NULL__null)
434 return false;
435
436 const char* name = NULL__null;
437 // The passed message is valid if it contains the right printer name.
438 bool valid = message != NULL__null
439 && message->FindString("printer_name", &name) == B_OK((int)0)
440 && strcmp(printerName, name) == 0;
441
442 free(printerName);
443 return valid;
444}
445
446
447// Either SetSettings() or ConfigPage() has to be called prior
448// to any of the getters otherwise they return undefined values.
449BRect
450BPrintJob::PaperRect()
451{
452 if (fDefaultSetupMessage == NULL__null)
453 _LoadDefaultSettings();
454
455 return fPaperSize;
456}
457
458
459BRect
460BPrintJob::PrintableRect()
461{
462 if (fDefaultSetupMessage == NULL__null)
463 _LoadDefaultSettings();
464
465 return fUsableSize;
466}
467
468
469void
470BPrintJob::GetResolution(int32* xdpi, int32* ydpi)
471{
472 if (fDefaultSetupMessage == NULL__null)
473 _LoadDefaultSettings();
474
475 if (xdpi != NULL__null)
476 *xdpi = fXResolution;
477
478 if (ydpi != NULL__null)
479 *ydpi = fYResolution;
480}
481
482
483int32
484BPrintJob::FirstPage()
485{
486 return fFirstPage;
487}
488
489
490int32
491BPrintJob::LastPage()
492{
493 return fLastPage;
494}
495
496
497int32
498BPrintJob::PrinterType(void*) const
499{
500 BMessenger printServer;
501 if (PrintServerMessenger::GetPrintServerMessenger(printServer) != B_OK((int)0))
502 return B_COLOR_PRINTER; // default
503
504 BMessage reply;
505 BMessage message(PSRV_GET_ACTIVE_PRINTER'pgcp');
506 printServer.SendMessage(&message, &reply);
507
508 int32 type;
509 if (reply.FindInt32("color", &type) != B_OK((int)0))
510 return B_COLOR_PRINTER; // default
511
512 return type;
513}
514
515
516// #pragma mark - private
517
518
519void
520BPrintJob::_RecurseView(BView* view, BPoint origin, BPicture* picture,
521 BRect rect)
522{
523 ASSERT(picture != NULL)(void)0;
524
525 BRegion region;
526 region.Set(BRect(rect.left, rect.top, rect.right, rect.bottom));
527 view->fState->print_rect = rect;
528
529 view->AppendToPicture(picture);
530 view->PushState();
531 view->SetOrigin(origin);
532 view->ConstrainClippingRegion(&region);
533
534 if (view->ViewColor() != B_TRANSPARENT_COLOR) {
535 rgb_color highColor = view->HighColor();
536 view->SetHighColor(view->ViewColor());
537 view->FillRect(rect);
538 view->SetHighColor(highColor);
539 }
540
541 if ((view->Flags() & B_WILL_DRAW) != 0) {
542 view->fIsPrinting = true;
543 view->Draw(rect);
544 view->fIsPrinting = false;
545 }
546
547 view->PopState();
548 view->EndPicture();
549
550 BView* child = view->ChildAt(0);
551 while (child != NULL__null) {
552 if (!child->IsHidden()) {
553 BPoint leftTop(view->Bounds().LeftTop() + child->Frame().LeftTop());
554 BRect printRect(rect.OffsetToCopy(rect.LeftTop() - leftTop)
555 & child->Bounds());
556 if (printRect.IsValid())
557 _RecurseView(child, origin + leftTop, picture, printRect);
558 }
559 child = child->NextSibling();
560 }
561
562 if ((view->Flags() & B_DRAW_ON_CHILDREN) != 0) {
563 view->AppendToPicture(picture);
564 view->PushState();
565 view->SetOrigin(origin);
566 view->ConstrainClippingRegion(&region);
567 view->fIsPrinting = true;
568 view->DrawAfterChildren(rect);
569 view->fIsPrinting = false;
570 view->PopState();
571 view->EndPicture();
572 }
573}
574
575
576void
577BPrintJob::_GetMangledName(char* buffer, size_t bufferSize) const
578{
579 snprintf(buffer, bufferSize, "%s@%" B_PRId64"ll" "d", fPrintJobName,
580 system_time() / 1000);
581}
582
583
584void
585BPrintJob::_HandlePageSetup(BMessage* setup)
586{
587 setup->FindRect(PSRV_FIELD_PRINTABLE_RECT"printable_rect", &fUsableSize);
588 setup->FindRect(PSRV_FIELD_PAPER_RECT"paper_rect", &fPaperSize);
589
590 // TODO verify data type (taken from libprint)
591 int64 valueInt64;
592 if (setup->FindInt64(PSRV_FIELD_XRES"xres", &valueInt64) == B_OK((int)0))
593 fXResolution = (short)valueInt64;
594
595 if (setup->FindInt64(PSRV_FIELD_YRES"yres", &valueInt64) == B_OK((int)0))
596 fYResolution = (short)valueInt64;
597}
598
599
600bool
601BPrintJob::_HandlePrintSetup(BMessage* message)
602{
603 _HandlePageSetup(message);
604
605 bool valid = true;
606 if (message->FindInt32(PSRV_FIELD_FIRST_PAGE"first_page", &fFirstPage) != B_OK((int)0))
607 valid = false;
608
609 if (message->FindInt32(PSRV_FIELD_LAST_PAGE"last_page", &fLastPage) != B_OK((int)0))
610 valid = false;
611
612 return valid;
613}
614
615
616void
617BPrintJob::_NewPage()
618{
619 // init, write new page_header
620 fCurrentPageHeader->next_page = 0;
621 fCurrentPageHeader->number_of_pictures = 0;
622 fCurrentPageHeaderOffset = fSpoolFile->Position();
623 fSpoolFile->Write(fCurrentPageHeader, sizeof(_page_header_));
624}
625
626
627void
628BPrintJob::_EndLastPage()
629{
630 if (!fSpoolFile)
631 return;
632
633 if (fCurrentPageHeader->number_of_pictures == 0)
634 return;
635
636 fSpoolFileHeader.page_count++;
637 fSpoolFile->Seek(0, SEEK_END2);
638 if (fCurrentPageHeaderOffset) {
639 fCurrentPageHeader->next_page = 0;
640 fSpoolFile->Seek(fCurrentPageHeaderOffset, SEEK_SET0);
641 fSpoolFile->Write(fCurrentPageHeader, sizeof(_page_header_));
642 fSpoolFile->Seek(0, SEEK_END2);
643 }
644}
645
646
647void
648BPrintJob::_AddSetupSpec()
649{
650 fSetupMessage->Flatten(fSpoolFile);
651}
652
653
654void
655BPrintJob::_AddPicture(BPicture& picture, BRect& rect, BPoint& where)
656{
657 ASSERT(fSpoolFile != NULL)(void)0;
658
659 fCurrentPageHeader->number_of_pictures++;
660 fSpoolFile->Write(&where, sizeof(BRect));
661 fSpoolFile->Write(&rect, sizeof(BPoint));
662 picture.Flatten(fSpoolFile);
663}
664
665
666/*! Returns a copy of the applications default printer name or NULL if it
667 could not be obtained. Caller is responsible to free the string using
668 free().
669*/
670char*
671BPrintJob::_GetCurrentPrinterName() const
672{
673 BMessenger printServer;
674 if (PrintServerMessenger::GetPrintServerMessenger(printServer) != B_OK((int)0))
6
Taking false branch
675 return NULL__null;
676
677 const char* printerName = NULL__null;
678
679 BMessage reply;
680 BMessage message(PSRV_GET_ACTIVE_PRINTER'pgcp');
681 if (printServer.SendMessage(&message, &reply) == B_OK((int)0))
7
Taking true branch
682 reply.FindString("printer_name", &printerName);
683
684 if (printerName == NULL__null)
8
Taking false branch
685 return NULL__null;
686
687 return strdup(printerName);
9
Memory is allocated
688}
689
690
691void
692BPrintJob::_LoadDefaultSettings()
693{
694 BMessenger printServer;
695 if (PrintServerMessenger::GetPrintServerMessenger(printServer) != B_OK((int)0))
696 return;
697
698 BMessage message(PSRV_GET_DEFAULT_SETTINGS'pdef');
699 BMessage* reply = new BMessage;
700
701 printServer.SendMessage(&message, reply);
702
703 // Only override our settings if we don't have any settings yet
704 if (fSetupMessage == NULL__null)
705 _HandlePrintSetup(reply);
706
707 delete fDefaultSetupMessage;
708 fDefaultSetupMessage = reply;
709}
710
711
712void BPrintJob::_ReservedPrintJob1() {}
713void BPrintJob::_ReservedPrintJob2() {}
714void BPrintJob::_ReservedPrintJob3() {}
715void BPrintJob::_ReservedPrintJob4() {}
716
717
718// #pragma mark -- PrintServerMessenger
719
720
721namespace BPrivate {
722
723
724PrintServerMessenger::PrintServerMessenger(uint32 what, BMessage *input)
725 :
726 fWhat(what),
727 fInput(input),
728 fRequest(NULL__null),
729 fResult(NULL__null),
730 fThreadCompleted(-1),
731 fHiddenApplicationModalWindow(NULL__null)
732{
733 RejectUserInput();
734}
735
736
737PrintServerMessenger::~PrintServerMessenger()
738{
739 DeleteSemaphore();
740 // in case SendRequest could not start the thread
741 delete fRequest; fRequest = NULL__null;
742 AllowUserInput();
743}
744
745
746void
747PrintServerMessenger::RejectUserInput()
748{
749 fHiddenApplicationModalWindow = new BAlert("bogus", "app_modal", "OK");
750 fHiddenApplicationModalWindow->DefaultButton()->SetEnabled(false);
751 fHiddenApplicationModalWindow->SetDefaultButton(NULL__null);
752 fHiddenApplicationModalWindow->SetFlags(fHiddenApplicationModalWindow->Flags() | B_CLOSE_ON_ESCAPE);
753 fHiddenApplicationModalWindow->MoveTo(-65000, -65000);
754 fHiddenApplicationModalWindow->Go(NULL__null);
755}
756
757
758void
759PrintServerMessenger::AllowUserInput()
760{
761 fHiddenApplicationModalWindow->Lock();
762 fHiddenApplicationModalWindow->Quit();
763}
764
765
766void
767PrintServerMessenger::DeleteSemaphore()
768{
769 if (fThreadCompleted >= B_OK((int)0)) {
770 sem_id id = fThreadCompleted;
771 fThreadCompleted = -1;
772 delete_sem(id);
773 }
774}
775
776
777status_t
778PrintServerMessenger::SendRequest()
779{
780 fThreadCompleted = create_sem(0, "print_server_messenger_sem");
781 if (fThreadCompleted < B_OK((int)0))
782 return B_ERROR(-1);
783
784 thread_id id = spawn_thread(MessengerThread, "async_request",
785 B_NORMAL_PRIORITY10, this);
786 if (id <= 0 || resume_thread(id) != B_OK((int)0))
787 return B_ERROR(-1);
788
789 // Get the originating window, if it exists
790 BWindow* window = dynamic_cast<BWindow*>(
791 BLooper::LooperForThread(find_thread(NULL__null)));
792 if (window != NULL__null) {
793 status_t err;
794 while (true) {
795 do {
796 err = acquire_sem_etc(fThreadCompleted, 1, B_RELATIVE_TIMEOUT,
797 50000);
798 // We've (probably) had our time slice taken away from us
799 } while (err == B_INTERRUPTED((-2147483647 - 1) + 10));
800
801 // Semaphore was finally nuked in SetResult(BMessage *)
802 if (err == B_BAD_SEM_ID(((-2147483647 - 1) + 0x1000) + 0))
803 break;
804 window->UpdateIfNeeded();
805 }
806 } else {
807 // No window to update, so just hang out until we're done.
808 while (acquire_sem(fThreadCompleted) == B_INTERRUPTED((-2147483647 - 1) + 10));
809 }
810
811 status_t status;
812 wait_for_thread(id, &status);
813
814 return Result() != NULL__null ? B_OK((int)0) : B_ERROR(-1);
815}
816
817
818BMessage*
819PrintServerMessenger::Request()
820{
821 if (fRequest != NULL__null)
822 return fRequest;
823
824 if (fInput != NULL__null) {
825 fRequest = new BMessage(*fInput);
826 fRequest->what = fWhat;
827 } else
828 fRequest = new BMessage(fWhat);
829
830 return fRequest;
831}
832
833
834void
835PrintServerMessenger::SetResult(BMessage* result)
836{
837 fResult = result;
838 DeleteSemaphore();
839 // terminate loop in thread spawned by SendRequest
840}
841
842
843status_t
844PrintServerMessenger::GetPrintServerMessenger(BMessenger& messenger)
845{
846 messenger = BMessenger(PSRV_SIGNATURE_TYPE"application/x-vnd.Be-PSRV");
847 return messenger.IsValid() ? B_OK((int)0) : B_ERROR(-1);
848}
849
850
851status_t
852PrintServerMessenger::MessengerThread(void* data)
853{
854 PrintServerMessenger* messenger = static_cast<PrintServerMessenger*>(data);
855
856 BMessenger printServer;
857 if (messenger->GetPrintServerMessenger(printServer) != B_OK((int)0)) {
858 ShowError(B_TRANSLATE("Print Server is not responding.")gSystemCatalog.GetString(("Print Server is not responding."),
"PrintJob")
);
859 messenger->SetResult(NULL__null);
860 return B_ERROR(-1);
861 }
862
863 BMessage* request = messenger->Request();
864 if (request == NULL__null) {
865 messenger->SetResult(NULL__null);
866 return B_ERROR(-1);
867 }
868
869
870 BMessage reply;
871 if (printServer.SendMessage(request, &reply) != B_OK((int)0)
872 || reply.what != 'okok' ) {
873 messenger->SetResult(NULL__null);
874 return B_ERROR(-1);
875 }
876
877 messenger->SetResult(new BMessage(reply));
878 return B_OK((int)0);
879}
880
881
882} // namespace BPrivate