Beispiel #1
0
int NetworkServer::proc(ProcJob *job){
	job->serv = this;
	job->result = PROC_OK;
	job->stime = millitime();

	const Protoc *req = job->req;

	do{
		Command *cmd = proc_map.get_proc(req->head.method);
		if(!cmd){
			log_warn("[%s] invalid method [ method: %s ].", job->link->get_basic_string(), req->head.method);
			job->link->response.head.status = 1;  //method does not exist
			break;
		}
		if(job->link->request.head.magic_num != magic_num){
			log_warn("[%s] invalid magic num [ magic_num: %u, config: %u ].", 
					job->link->get_basic_string(), req->head.magic_num, magic_num);
			job->link->response.head.status = 2; //invalid magic num
			break;
		}
		if(job->link->request.head.bodylen > MAX_PACKAGE_SIZE){
			log_warn("[%s] request body too big [ body len: %u, max: %u ].", 
					job->link->get_basic_string(), job->link->request.head.bodylen, MAX_PACKAGE_SIZE);
			job->link->response.head.status = 3; //invalid magic num
			break;
		}
		job->cmd = cmd;
		if(cmd->flags & Command::FLAG_THREAD){
			if(cmd->flags & Command::FLAG_WRITE){
				log_frame("[%s] command with write property, push it to backend thread [ logid: %llu, method: %s ]",
						job->link->get_basic_string(), job->link->response.head.logid, job->link->response.head.method);
				if(-1 == writer->push(job)){
					log_warn("[%s] push job into writer queue failed.", job->link->get_basic_string());
					job->link->response.head.status = 5;  //other system error
				}
			}else{
				log_frame("[%s] command with read property, push it to backend thread [ logid: %llu, method: %s ]",
						job->link->get_basic_string(), job->link->response.head.logid, job->link->response.head.method);
				if(-1 == reader->push(job)){
					log_warn("[%s] push job into reader queue failed.", job->link->get_basic_string());
					job->link->response.head.status = 5;   //other system error
				}
			}
			return PROC_THREAD;
		}
		log_frame("[%s] command will be processed in main thread [ logid: %llu, method: %s ]",
				job->link->get_basic_string(), job->link->response.head.logid, job->link->response.head.method);
		proc_t p = cmd->proc;
		job->time_wait = 1000 * (millitime() - job->stime);
		job->result = (*p)(this, job->link, *req, &job->link->response);
		job->time_proc = 1000 * (millitime() - job->stime) - job->time_wait;
	}while(0);

	return job->result;
}
Beispiel #2
0
int NetworkServer::proc_result(ProcJob *job, ready_list_t *ready_list){
	Link *link = job->link;
	int result = job->result;

	log_debug("[%s] process finished, wait time:%.3f,proc time:%.3f, method: %s, status: %u",
			job->link->get_basic_string(), job->time_wait, job->time_proc,
			job->req->head.method,
			job->link->response.head.status);
	if(job->cmd){
		job->cmd->calls += 1;
		job->cmd->time_wait += job->time_wait;
		job->cmd->time_proc += job->time_proc;
	}
	SAFE_DELETE(job);
	int len = 0;
	if(result == PROC_ERROR){
		log_info("[%s] fd: %d, proc error, maybe network is unavailable, delete link", link->get_basic_string(), link->fd());
		goto proc_err;
	}
	//try to write for one time
	//if there is no writing buffer, 0 will be returned
	len = link->write();
	if(len < 0){
		log_warn("[%s] fd: %d, write: %d, delete link", link->get_basic_string(), link->fd(), len);
		goto proc_err;
	}

	if(link->response.head.bodylen + sizeof(head_t) > link->writed){
		//need more writing operation
		fdes->set(link->fd(), FDEVENT_OUT, 1, link);
	}else{
		if(!long_connect || 0 != link->response.head.status){
			//TODO: for short connection
			link_count--;
			fdes->del(link->fd());
			log_frame("[%s] short connection, close [ fd: %d ]", link->get_basic_string(), link->fd());
			SAFE_DELETE(link);
		}else{
			//TODO: long connection£¬ continue to read data
			link->readed = link->writed = 0;
			link->request.reset();
			link->response.reset();
			link->reset_basic_string();
			fdes->set(link->fd(), FDEVENT_IN, 1, link);
			log_frame("[%s] long connection, try to receive request next time [ fd: %d ]", link->get_basic_string(), link->fd());
		}
	}
	return PROC_OK;
proc_err:
	this->link_count --;
	fdes->del(link->fd());
	SAFE_DELETE(link);
	return PROC_ERROR;
}
Beispiel #3
0
int NetworkServer::proc_client_event(const Fdevent *fde, ready_list_t *ready_list){
	Link *link = (Link *)fde->data.ptr;
	if(fde->events & FDEVENT_ERR){
		ready_list->push_back(link);
		log_warn("fd: %d, wait error, delete link", link->fd());
		link->mark_error();
		return 0;
	}
	if(fde->events & FDEVENT_IN){
		ready_list->push_back(link);
		if(link->error()){
			return 0;
		}
		int len = link->read();
		if(len <= 0){
			if(link->readed < sizeof(head_t) || link->request.head.bodylen < MAX_PACKAGE_SIZE){
				log_frame("fd: %d, read: %d, delete link [ readed: %d, head_size: %d, bodylen: %u, max: %d ]", 
						link->fd(), len, link->readed, sizeof(head_t), link->request.head.bodylen, MAX_PACKAGE_SIZE);
				link->mark_error();
			}
			return 0;
		}
	}
	if(fde->events & FDEVENT_OUT){
		if(link->error()){
			return 0;
		}
		int len = link->write();
		if(len < 0){
			log_warn("[%s] fd: %d, write: %d, delete link", link->get_basic_string(), link->fd(), len);
			link->mark_error();
			return 0;
		}
		if(link->response.head.bodylen + sizeof(head_t) <= link->writed){
			log_frame("[%s] fd: %d, write: %d, finish writing", link->get_basic_string());
			fdes->clr(link->fd(), FDEVENT_OUT);
		}
		if(!long_connect || 0 != link->response.head.status){
			link_count--;
			fdes->del(link->fd());
			log_frame("[%s] short connection, close [ fd: %d ]", link->get_basic_string(), link->fd());
			SAFE_DELETE(link);
		}else{
			link->readed = link->writed = 0;
			link->request.reset();
			link->response.reset();
			link->reset_basic_string();
			fdes->set(link->fd(), FDEVENT_IN, 1, link);
			log_frame("[%s] long connection, try to receive request next time [ fd: %d ]", link->get_basic_string(), link->fd());
		}
	}
	return 0;
}
Beispiel #4
0
HRESULT WINAPI my_CreateDXGIFactory1( REFIID riid, void **ppFactory )
{
	log_frame( "dxgi", u::info ) << u::endh;
	HRESULT result = (*stub_CreateDXGIFactory1)(riid, ppFactory);
	frame << log_ret(result);
	return result;
}
Beispiel #5
0
BOOL WINAPI my_UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize, HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend, DWORD dwFlags )
{
	log_frame( "gdi", u::info ) << log_var(hwnd) << u::endh;
	BOOL result = (*stub_UpdateLayeredWindow)( hwnd, hdcDst, pptDst, psize, hdcSrc, pptSrc, crKey, pblend, dwFlags );
	frame << log_ret(result);
	return result;
}
Beispiel #6
0
HRESULT STDMETHODCALLTYPE my_CreateSwapChain( IDXGIFactory* This, IUnknown* ifDevice, DXGI_SWAP_CHAIN_DESC* pdesc, IDXGISwapChain** ppSwapChain )
{
	log_frame( "dxgi", u::info ) << log_var(ifDevice) << log_var(pdesc->OutputWindow) << log_var(pdesc->BufferCount) <<
		log_var(pdesc->BufferDesc.Width) << log_var(pdesc->BufferDesc.Height) << u::endh;
	HRESULT result = (*stub_CreateSwapChain)( This, ifDevice, pdesc, ppSwapChain );
	frame << log_ret(result);
	return result;
}
Beispiel #7
0
int WINAPI my_ReleaseDC( HWND hwnd, HDC hdc )
{
	log_frame( "user", u::info ) << log_var(hwnd) << log_var(hdc) << u::endh;

	int result = (*stub_ReleaseDC)( hwnd, hdc );

	frame << log_ret(result);
	return result;
}
Beispiel #8
0
int WINAPI my_BitBlt( HDC hdc, int x, int y, int cx, int cy, HDC hdcSrc, int x1, int y1, DWORD rop )
{
	log_frame( "gdi", u::info ) << log_var(hdc) << log_var(x) << log_var(y) << log_var(cx) << log_var(cy) << log_var(rop) << u::endh;

	BOOL result = (*stub_BitBlt)( hdc, x, y, cx, cy, hdcSrc, x1, y1, rop );

	frame << log_ret(result);
	return result;
}
Beispiel #9
0
HRESULT STDMETHODCALLTYPE my_CreateSwapChainForHwnd( IDXGIFactory2* This, IUnknown* pDevice, HWND hWnd, const DXGI_SWAP_CHAIN_DESC1* pDesc, 
	const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc, IDXGIOutput* pRestrictToOutput, IDXGISwapChain1** ppSwapChain )
{
	log_frame( "dxgi", u::info ) << log_var(pDevice) << log_var(hWnd) << 
		log_var(pDesc->Width) << log_var(pDesc->Height) << log_var(pDesc->BufferCount) << u::endh;
	HRESULT result = (*stub_CreateSwapChainForHwnd)( This, pDevice, hWnd, pDesc, pFullscreenDesc, pRestrictToOutput, ppSwapChain );
	frame << log_var(*ppSwapChain) << log_ret(result);
	return result;
}
Beispiel #10
0
HDC WINAPI my_GetDC( HWND hwnd )
{
	log_frame( "user", u::info ) << log_var(hwnd) << u::endh;

	HDC hdc = (*stub_GetDC)( hwnd );

	frame << log_ret(hdc);
	return hdc;
}
Beispiel #11
0
void STDMETHODCALLTYPE my_DrawGlyphRun( ID2D1RenderTarget* This, D2D1_POINT_2F baselineOrigin, const DWRITE_GLYPH_RUN* glyphRun, ID2D1Brush *foregroundBrush, DWRITE_MEASURING_MODE measuringMode )
{
	log_frame( "d2d1", u::info ) << log_var(This) << log_var(baselineOrigin.x) << log_var(baselineOrigin.y) <<
		log_var(glyphRun->glyphCount) << u::endh;

    g_currentRtWithGlyph = This;

	(*stub_DrawGlyphRun)( This, baselineOrigin, glyphRun, foregroundBrush, measuringMode );
	
	return;
}
Beispiel #12
0
HRESULT STDMETHODCALLTYPE my_CreateBitmapFromWicBitmap( ID2D1RenderTarget* This, IWICBitmapSource* wicBitmapSource, const D2D1_BITMAP_PROPERTIES* bitmapProperties, ID2D1Bitmap** bitmap )
{
	log_frame( "d2d1", u::info ) << log_var(This) << log_var(wicBitmapSource);

	double dpix, dpiy;
	UINT width, height;
	wicBitmapSource->GetResolution( &dpix, &dpiy );
	wicBitmapSource->GetSize( &width, &height );
	frame << log_var(dpix) << log_var(dpiy) << log_var(width) << log_var(height) << u::endh;

	HRESULT result = (*stub_CreateBitmapFromWicBitmap)( This, wicBitmapSource, bitmapProperties, bitmap );

	frame << log_var(*bitmap) << log_ret(result);
	return result;
}
Beispiel #13
0
HRESULT STDMETHODCALLTYPE my_Present( IDXGISwapChain* This, UINT SyncInterval, UINT Flags )
{
	log_frame( "dxgi", u::info ) << log_var(This) << u::endh;
	HRESULT hr;

	DXGI_SWAP_CHAIN_DESC desc;
	hr = This->GetDesc( &desc );
	frame << log_var(desc.BufferDesc.Width) << log_var(desc.BufferDesc.Height) << log_var(desc.OutputWindow);

	CComPtr<IDXGIDevice> dxgiDevice;
	hr = This->GetDevice( __uuidof(IDXGIDevice), (void**)&dxgiDevice );
	frame << log_var(dxgiDevice);

	HRESULT result = stub_Present(This, SyncInterval, Flags );
	frame << log_ret(result);
	return result;
}
Beispiel #14
0
HRESULT STDMETHODCALLTYPE my_CreateWicBitmapRenderTarget( ID2D1Factory* This, IWICBitmap* target, const D2D1_RENDER_TARGET_PROPERTIES *renderTargetProperties, ID2D1RenderTarget** renderTarget )
{
	log_frame( "d2d1", u::info ) << log_var(This) << log_var(target) << u::endh;

	// Some data about the bitmap
	UINT width, height;
	double dpix, dpiy;
	target->GetSize( &width, &height );
	target->GetResolution( &dpix, &dpiy );
	frame << log_var(width) << log_var(height);
	frame << log_var(dpix) << log_var(dpiy);

	HRESULT result = (*stub_CreateWicBitmapRenderTarget)( This, target, renderTargetProperties, renderTarget );
	
	frame << log_var(*renderTarget) << log_ret(result);
	return result;
}
Beispiel #15
0
LRESULT WINAPI my_DispatchMessage( const MSG *pmsg )
{
	log_frame( "user", u::info ) << log_var(pmsg->hwnd) << log_var_f(pmsg->message, "%x") << u::endh;
	LRESULT result = (*stub_DispatchMessage)(pmsg);

	if( pmsg->message == 0x401 ) {
		CPlug* pplug = CPlug::inst();
		if( pplug ) {
			CSubclsWnd* pwnd = pplug->getSubclsWnd();
			if( pwnd ) {
		        //CPlug::inst()->getSubclsWnd()->highlight();
			}
		}
	}

	frame << log_ret(result);
	return result; 
}
Beispiel #16
0
HRESULT STDMETHODCALLTYPE my_Present1( IDXGISwapChain1* This, UINT SyncInterval, UINT PresentFlags, const DXGI_PRESENT_PARAMETERS *pPresentParameters )
{
	log_frame( "dxgi", u::info ) << log_var(This) << u::endh;
	HRESULT hr;

	DXGI_SWAP_CHAIN_DESC1 desc;
	hr = This->GetDesc1( &desc );
	frame << log_var(desc.Width) << log_var(desc.Height);

	HWND hwnd;
	hr = This->GetHwnd( &hwnd );
	frame << log_var(hwnd);

	CComPtr<IDXGIDevice> dxgiDevice;
	hr = This->GetDevice( __uuidof(IDXGIDevice), (void**)&dxgiDevice );
	frame << log_var(dxgiDevice);

	HRESULT result = (*stub_Present1)(This, SyncInterval, PresentFlags, pPresentParameters );
	frame << log_ret(result);
	return result;
}
Beispiel #17
0
void STDMETHODCALLTYPE my_DrawBitmap( ID2D1RenderTarget* This, ID2D1Bitmap* bitmap, const D2D1_RECT_F* destRc, FLOAT opacity, 
								  D2D1_BITMAP_INTERPOLATION_MODE interpolationMode, const D2D1_RECT_F* srcRc )
{
	log_frame( "d2d1", u::info ) << log_var(This) << log_var(bitmap) << log_var(opacity);

	D2D1_SIZE_F bitmapSize = bitmap->GetSize( );
	frame << log_var(bitmapSize.width) << log_var(bitmapSize.height);

	if( destRc ) {
		frame << log_var(destRc->left) << log_var(destRc->top) << log_var(destRc->right) << log_var(destRc->bottom);
	}

	if( srcRc ) {
		frame << log_var(srcRc->left) << log_var(srcRc->top) << log_var(srcRc->right) << log_var(srcRc->bottom);
	}

	frame << u::endh;

	(*stub_DrawBitmap)(This, bitmap, destRc, opacity, interpolationMode, srcRc );

	return;
}
/**********************************************************************************************************************
	CProcessBase::Flush_System_Messages -- Manager and log messages get sent separately from other messages.
		This function must be the last function called in this thread's execution context/tbb-execute.  The instant a reschedule
		message is pushed to the manager, this thread may end up getting reexecuted which would cause data corruption
		if the current execution is still ongoing.
					
**********************************************************************************************************************/
void CProcessBase::Flush_System_Messages( void )
{
	bool is_shutting_down = Is_Shutting_Down();

	// Flush logging messages if possible
	if ( LoggingMailbox.get() != nullptr && LogFrame.get() != nullptr )
	{
		shared_ptr< CProcessMessageFrame > log_frame( LogFrame );
		LogFrame.reset();

		LoggingMailbox->Add_Frame( log_frame );
	}

	// Clear log interface if necessary
	if ( is_shutting_down )
	{
		LoggingMailbox.reset();
	}

	// Flush manager messages if possible
	if ( ManagerMailbox.get() != nullptr && ManagerFrame.get() != nullptr )
	{
		shared_ptr< CProcessMessageFrame > manager_frame( ManagerFrame );
		ManagerFrame.reset();

		ManagerMailbox->Add_Frame( manager_frame );
	}

	// Clear manager interface if necessary
	if ( is_shutting_down )
	{
		// logically safe to do even after we've pushed messages
		// A thread should not be rescheduled if it's in the shut down stage, and even it did
		// get rescheduled, the subsequent execution of the thread does nothing and does not access
		// the manager interface
		ManagerMailbox.reset();	
	}
}
static void log_sysinfo(void)
{
	struct rx_meas_stat *meas = &ms->meas;
	struct gsm48_sysinfo *s = &sysinfo;
	int8_t rxlev;
	char ta_str[32] = "";

	if (log_si.ta != 0xff)
		sprintf(ta_str, " TA=%d", log_si.ta);

	LOGP(DSUM, LOGL_INFO, "Cell: ARFCN=%d MCC=%s MNC=%s (%s, %s)%s\n",
		arfcn, gsm_print_mcc(s->mcc), gsm_print_mnc(s->mnc),
		gsm_get_mcc(s->mcc), gsm_get_mnc(s->mcc, s->mnc), ta_str);

	LOGFILE("[sysinfo]\n");
	LOGFILE("arfcn %d\n", s->arfcn);
	log_time();
	log_gps();
	LOGFILE("bsic %d,%d\n", s->bsic >> 3, s->bsic & 7);
	rxlev = meas->rxlev / meas->frames - 110;
	LOGFILE("rxlev %d\n", rxlev);
	if (s->si1)
		log_frame("si1", s->si1_msg);
	if (s->si2)
		log_frame("si2", s->si2_msg);
	if (s->si2bis)
		log_frame("si2bis", s->si2b_msg);
	if (s->si2ter)
		log_frame("si2ter", s->si2t_msg);
	if (s->si3)
		log_frame("si3", s->si3_msg);
	if (s->si4)
		log_frame("si4", s->si4_msg);
	if (log_si.ta != 0xff)
		LOGFILE("ta %d\n", log_si.ta);

	LOGFILE("\n");
	LOGFLUSH();
}
Beispiel #20
0
void STDMETHODCALLTYPE my_BeginDraw( ID2D1RenderTarget* This )
{
	log_frame( "d2d1", u::info ) << log_var(This) << u::endh;
	(*stub_BeginDraw)( This );
	return;
}
Beispiel #21
0
void NetworkServer::serve(){
	{ 
		auto_mask mask(3, SIGPIPE, SIGINT, SIGTERM, SIGQUIT);
		writer = new (std::nothrow)ProcWorkerPool("writer");
		ASSERT_SYS(NULL != writer, "try to new ProcWorkerPool failed, no memory");
	    writer->start(num_writers);
	    reader = new (std::nothrow)ProcWorkerPool("reader");
		ASSERT_SYS(NULL != reader, "try to new ProcWorkerPool failed, no memory");
	    reader->start(num_readers);
	}
	ready_list_t ready_list;
	ready_list_t ready_list_2;
	ready_list_t::iterator it;
	const Fdevents::events_t *events;

	fdes->set(serv_link->fd(), FDEVENT_IN, 0, serv_link);
	fdes->set(this->reader->fd(), FDEVENT_IN, 0, this->reader);
	fdes->set(this->writer->fd(), FDEVENT_IN, 0, this->writer);

	uint32_t last_ticks = g_ticks;
	while(!quit){
		if((uint32_t)(g_ticks - last_ticks) >= STATUS_REPORT_TICKS){
			last_ticks = g_ticks;
			log_info("server is running, links: %d", this->link_count);
		}
		ready_list.swap(ready_list_2);
		ready_list_2.clear();

		if(!ready_list.empty()){
			events = fdes->wait(0);
		}else{
			events = fdes->wait(50);
		}
		if(events == NULL){
			log_fatal("events.wait error: %s", strerror(errno));
			break;
		}
		
		for(int i=0; i<(int)events->size(); i++){
			const Fdevent *fde = events->at(i);
			if(fde->data.ptr == serv_link){
				Link *link = accept_link();
				if(link){
					this->link_count ++;				
					log_debug("new link from %s:%d, fd: %d, links count: %d",
							link->remote_ip, link->remote_port, 
							link->fd(), this->link_count);

					fdes->set(link->fd(), FDEVENT_IN, 1, link);
				}
			}else if(fde->data.ptr == this->reader || fde->data.ptr == this->writer){
				ProcWorkerPool *worker = (ProcWorkerPool *)fde->data.ptr;
				ProcJob *job = NULL;
				if(worker->pop(&job) == 0){
					log_fatal("reading result from workers error!");		
					exit(0);
				}
				if(proc_result(job, &ready_list) == PROC_ERROR){
					//
				}

			}else{
				proc_client_event(fde, &ready_list);
			}
		}

		for(it = ready_list.begin(); it != ready_list.end(); it ++){
			Link *link = *it;
			if(link->error()){
				this->link_count --;
				fdes->del(link->fd());
				SAFE_DELETE(link);
				continue;
			}

			if(link->readed >= sizeof(head_t) && 0x00 == link->get_basic_string()[0]){
				if(0 == link->request.head.logid){
					link->request.head.logid = pow(2, 64) * (rand() / (RAND_MAX + 1.0));
				}
				link->add_basic_info("client_ip", link->remote_ip);
				link->add_basic_info("client_port", link->remote_port);
				link->add_basic_info("logid", link->request.head.logid);
				link->add_basic_info("method", link->request.head.method);
				link->add_basic_info("magic_num", link->request.head.magic_num);
			}
			if(link->readed >= sizeof(head_t) && link->request.head.bodylen > MAX_PACKAGE_SIZE){
				log_frame("[ %s ]fd: %d, body len is too big, give up reading[ body len: %u, max: %u ].", 
						link->get_basic_string(), link->request.head.bodylen, MAX_PACKAGE_SIZE);
				fdes->del(link->fd());
			}else if(link->readed < sizeof(head_t) || link->request.head.bodylen + sizeof(head_t) > link->readed){
				//head has not been read over or body has not been read over, continue to read
				log_frame("[ %s ]fd: %d, readed: %d, bodylen: %u, continue to read", 
						(link->readed >= sizeof(head_t) ? link->get_basic_string() : ""), link->fd(), 
						link->readed, link->request.head.bodylen);
				fdes->set(link->fd(), FDEVENT_IN, 1, link);
				continue;
			}else{
				log_frame("[ %s ]fd: %d, readed: %d, bodylen: %u, read data finished", link->get_basic_string(), link->fd(), 
						link->readed, link->request.head.bodylen);
				fdes->del(link->fd());
			}
			link->active_time = millitime();
			
			//prepare response head first
			link->response.head = link->request.head;
			snprintf(link->response.head.provider, sizeof(link->response.head.provider), "%s", provider);
			link->response.head.bodylen = 0;

			ProcJob *job = new (std::nothrow)ProcJob();
			ASSERT_SYS(NULL != job, "try to new ProcJob failed, no memory");
			job->link = link;
			job->req = &link->request;
			int result = this->proc(job);

			if(result == PROC_THREAD){
				fdes->del(link->fd());
				continue;
			}
			if(result == PROC_BACKEND){
				job->req = &link->request;
				this->link_count --;
				continue;

			}
			if(proc_result(job, &ready_list_2) == PROC_ERROR){
				//
			}

		} 
		// end foreach ready link
	}
}
Beispiel #22
0
HRESULT STDMETHODCALLTYPE my_EndDraw( ID2D1RenderTarget* This, D2D1_TAG *tag1, D2D1_TAG *tag2 )
{
	HRESULT hr;
	log_frame( "d2d1", u::info ) << log_var(This) << u::endh;

    if( g_currentRtWithGlyph == This ) {

	    CComPtr<ID2D1SolidColorBrush> ifBrushBlack;
	    CComPtr<ID2D1SolidColorBrush> ifBrushRed;
	    CComPtr<ID2D1SolidColorBrush> ifBrushGreen;
	    CComPtr<ID2D1SolidColorBrush> ifBrushBlue;
        CComPtr<ID2D1SolidColorBrush> ifBrushOrange;

	    hr = This->CreateSolidColorBrush( D2D1::ColorF( D2D1::ColorF::Black ), &ifBrushBlack );
	    hr = This->CreateSolidColorBrush( D2D1::ColorF( D2D1::ColorF::Red ), &ifBrushRed );
	    hr = This->CreateSolidColorBrush( D2D1::ColorF( D2D1::ColorF::Green ), &ifBrushGreen );
	    hr = This->CreateSolidColorBrush( D2D1::ColorF( D2D1::ColorF::Blue ), &ifBrushBlue );
        hr = This->CreateSolidColorBrush( D2D1::ColorF( D2D1::ColorF::OrangeRed, 0.5f ), &ifBrushOrange );

	    D2D1_RECT_F rect;
	    rect.left = 0;
	    rect.top = 0;
	    rect.right = 1024;
	    rect.bottom = 2014;
	    //This->PushAxisAlignedClip( &rect, D2D1_ANTIALIAS_MODE_PER_PRIMITIVE );
	    //This->DrawLine( D2D1::Point2F(0.0f, 0.0f), D2D1::Point2F(480.0f, 480.0f), ifBrush );

        if( CPlug::inst()->IsDoingGrid() ) {
	        for( int i=0; i<20; ++i ) {

		        for( int j=0; j<20; ++j ) {
			        float cy = i * 50.0f;
			        float cx = j * 50.0f;

			        ID2D1SolidColorBrush* ifBrush = 
				        ( i<10 && j < 10 ) ? ifBrushBlack :
				        ( i<10 ) ? ifBrushRed :
				        ( j<10 ) ? ifBrushGreen :
				        ifBrushBlue;

			        This->DrawLine( D2D1::Point2F( cx - 5.0f, cy - 5.0f ), D2D1::Point2F( cx + 5.0f, cy + 5.0f ), ifBrush );
			        This->DrawLine( D2D1::Point2F( cx + 5.0f, cy - 5.0f ), D2D1::Point2F( cx - 5.0f, cy + 5.0f ), ifBrush );
		        }
	        }
	        //This->PopAxisAlignedClip();
        }

        if( CPlug::inst()->IsDoingRosebud() ) {
            CPlug* pplug = CPlug::inst();
            if( pplug ) {
                int num;
                int i;

                num = pplug->numRosebuds( );

                for( i = 0; i < num; ++i ) {
                    int ileft, itop, iright, ibottom;
                    bool f = pplug->enumRosebud( i, &ileft, &itop, &iright, &ibottom );

                    if( f ) {
                        float left = (float)ileft;
                        float top = (float)itop;
                        float right = (float)iright;
                        float bottom = (float)ibottom;

                        //This->DrawLine( D2D1::Point2F( left, top ), D2D1::Point2F( right, top ), ifBrushBlack );
                        //This->DrawLine( D2D1::Point2F( right, top ), D2D1::Point2F( right, bottom ), ifBrushBlack );
                        //This->DrawLine( D2D1::Point2F( right, bottom ), D2D1::Point2F( left, bottom ), ifBrushBlack );
                        //This->DrawLine( D2D1::Point2F( left, bottom ), D2D1::Point2F( left, top ), ifBrushBlack );

                        D2D1_RECT_F rc = D2D1::RectF( left, top, right, bottom );
                        This->FillRectangle( &rc, ifBrushOrange );

                    }
                }
            }

        }
        g_currentRtWithGlyph = NULL;
    }

	HRESULT result = stub_EndDraw(This, tag1, tag2 );
	frame << log_ret(result);
	return result;
}