GME
13
|
00001 #include <stdafx.h> 00002 #include <afxadv.h> 00003 #include "afxcoll.h" 00004 #include "afxtempl.h" 00005 #include "meta.h" 00006 #include "mga.h" 00007 #include "parser.h" 00008 00009 #include <algorithm> 00010 #include "CommonMfc.h" 00011 00012 #include "GMEstd.h" 00013 00014 #include "GMEOLEData.h" 00015 00016 #ifdef min 00017 #undef min 00018 #endif 00019 00020 CLIPFORMAT CGMEDataSource::cfGMEDesc = (CLIPFORMAT)(RegisterClipboardFormat(_T("GME Descriptor"))); 00021 int CGMEDataSource::myData = 0; 00022 00023 /* --------------------------- CGMEDataDescriptor --------------------------- */ 00024 //static // called externally, to destruct certain lists 00025 void CGMEDataDescriptor::destructList( CTypedPtrList<CPtrList, CRect *>& pList)// it is a CRectList 00026 { 00027 POSITION pos = pList.GetHeadPosition(); 00028 while(pos) 00029 delete pList.GetNext(pos); 00030 pList.RemoveAll(); 00031 } 00032 00033 CGMEDataDescriptor::CGMEDataDescriptor(CTypedPtrList<CPtrList, CRect *> &list, CTypedPtrList<CPtrList, CRect *> &annList,CPoint dragPoint,CPoint offs) 00034 { 00035 POSITION pos = list.GetHeadPosition(); 00036 while(pos) { 00037 CRect *rect = new CRect(list.GetNext(pos)); 00038 rect->OffsetRect(-dragPoint.x,-dragPoint.y); 00039 rects.AddTail(rect); 00040 } 00041 00042 pos = annList.GetHeadPosition(); 00043 while (pos) { 00044 CRect *rect = new CRect(annList.GetNext(pos)); 00045 rect->OffsetRect(-dragPoint.x,-dragPoint.y); 00046 annRects.AddTail(rect); 00047 } 00048 00049 offset = offs; 00050 pFile = 0; 00051 } 00052 00053 void CGMEDataDescriptor::Reset() 00054 { 00055 POSITION pos = rects.GetHeadPosition(); 00056 while(pos) 00057 delete rects.GetNext(pos); 00058 rects.RemoveAll(); 00059 00060 pos = annRects.GetHeadPosition(); 00061 while(pos) 00062 delete annRects.GetNext(pos); 00063 annRects.RemoveAll(); 00064 } 00065 00066 void CGMEDataDescriptor::Serialize(CArchive& ar) 00067 { 00068 if(ar.IsStoring()) { 00069 ar << (int)rects.GetCount(); 00070 POSITION pos = rects.GetHeadPosition(); 00071 while(pos) 00072 ar << *(rects.GetNext(pos)); 00073 00074 ar << (int)annRects.GetCount(); 00075 pos = annRects.GetHeadPosition(); 00076 while(pos) 00077 ar << *(annRects.GetNext(pos)); 00078 00079 ar << offset; 00080 } 00081 else { 00082 Reset(); 00083 int n; 00084 ar >> n; 00085 for(int i = 0; i < n; i++) { 00086 CRect *rect = new CRect(); 00087 ar >> *rect; 00088 rects.AddTail(rect); 00089 } 00090 00091 ar >> n; 00092 for(int j = 0; j < n; j++) { 00093 CRect *rect = new CRect(); 00094 ar >> *rect; 00095 annRects.AddTail(rect); 00096 } 00097 ar >> offset; 00098 } 00099 } 00100 00101 bool CGMEDataDescriptor::Load(COleDataObject* pDataObject) 00102 { 00103 ASSERT( pDataObject != NULL ); 00104 00105 if(pDataObject->IsDataAvailable(CGMEDataSource::cfGMEDesc)) { 00106 ASSERT(pFile == 0); 00107 pFile = pDataObject->GetFileData(CGMEDataSource::cfGMEDesc); 00108 ASSERT( pFile != NULL ); 00109 CArchive ar(pFile,CArchive::load); 00110 Serialize(ar); 00111 return true; 00112 } 00113 return false; 00114 } 00115 00116 int CGMEDataDescriptor::GetCount() 00117 { 00118 /* return (rects.GetCount() + annRects.GetCount()); */ 00119 return rects.GetCount(); 00120 } 00121 00122 void CGMEDataDescriptor::Clean() 00123 { 00124 delete pFile; 00125 pFile = 0; 00126 } 00127 00128 void CGMEDataDescriptor::Draw(CDC *pDC,CPoint &pt) 00129 { 00130 POSITION pos = rects.GetHeadPosition(); 00131 while(pos) { 00132 CRect rect = *(rects.GetNext(pos)); 00133 00134 rect.OffsetRect(pt); 00135 CPoint align = rect.CenterPoint(); 00136 00137 // Emulate the grid. 00138 long gs = GME_GRID_SIZE; 00139 rect.MoveToXY(rect.left / gs * gs, rect.top / gs * gs); 00140 00141 pDC->DrawFocusRect(&rect); 00142 } 00143 00144 pos = annRects.GetHeadPosition(); 00145 while (pos) { 00146 CRect rect = *(annRects.GetNext(pos)); 00147 00148 rect.OffsetRect(pt); 00149 pDC->DrawFocusRect(&rect); 00150 } 00151 } 00152 00153 00154 // This function has been simplified for GMEActiveBrowser 00155 // No annotations and grid alignment 00156 void CGMEDataDescriptor::SimpleDraw(CDC *pDC, CPoint &pt) 00157 { 00158 POSITION pos = rects.GetHeadPosition(); 00159 while(pos) { 00160 CRect rect = *(rects.GetNext(pos)); 00161 00162 rect.OffsetRect(pt); 00163 00164 pDC->DrawFocusRect(&rect); 00165 00166 } 00167 00168 } 00169 00170 00171 void CGMEDataDescriptor::GetBoundingRect(CRect &rBoundingRect) 00172 { 00173 rBoundingRect=CRect(0,0,0,0); 00174 00175 CRect Rect; 00176 POSITION pos=rects.GetHeadPosition(); 00177 00178 while(pos) 00179 { 00180 Rect=*(rects.GetNext(pos)); 00181 rBoundingRect.UnionRect(rBoundingRect,Rect); 00182 } 00183 00184 00185 } 00186 00187 00188 /* --------------------------- CGMEDataSource ------------------------------- */ 00189 00190 bool CGMEDataSource::IsGmeNativeDataAvailable(COleDataObject *pDataObject, IMgaProject *project) 00191 { 00192 ASSERT( project != NULL ); 00193 00194 CComPtr<IDataObject> p = pDataObject->GetIDataObject(FALSE); 00195 CComPtr<IMgaDataSource> source; 00196 if( p!= NULL && p.QueryInterface(&source) == S_OK ) 00197 { 00198 CComPtr<IUnknown> unknown; 00199 HRESULT hr = source->get_Project(&unknown); 00200 if (hr == HRESULT_FROM_WIN32(RPC_S_CALL_FAILED)) // crashrpt 17f8cc45-c369-464b-8162-5dc7bf3bf04c 00201 return false; 00202 COMTHROW(hr); 00203 ASSERT( unknown != NULL ); 00204 00205 if (unknown == NULL) 00206 { 00207 // Likely a race, crashrpt e27fb137-199a-4ff8-842e-301655495738 00208 return false; 00209 } 00210 00211 CComPtr<IMgaProject> source_project; 00212 // KMS: fixing crashrpt 8895373f-396e-490f-b882-036ba9d42961: this QI may fail 00213 hr = unknown.QueryInterface(&source_project); 00214 if ( source_project == NULL ) { 00215 ASSERT(false); 00216 return false; 00217 } 00218 00219 return source_project.IsEqualObject(project); 00220 } 00221 return false; 00222 } 00223 00224 bool CGMEDataSource::IsXMLDataAvailable(COleDataObject *pDataObject) 00225 { 00226 ASSERT( pDataObject != NULL ); 00227 00228 return pDataObject->IsDataAvailable(CF_UNICODETEXT) != FALSE; 00229 } 00230 00231 bool CGMEDataSource::ParseXMLData(COleDataObject *pDataObject, IMgaObject *target, bool merge = false) 00232 { 00233 ASSERT( pDataObject != NULL ); 00234 ASSERT( target != NULL ); 00235 00236 // create a temporary filename 00237 TCHAR *fname = _ttempnam(_T("c:\\temp"), _T("GMEtmp")); 00238 CString filename = fname; 00239 free(fname); 00240 00241 try 00242 { 00243 // get the memory file 00244 CFile *memfile = pDataObject->GetFileData(CF_UNICODETEXT); 00245 if( memfile == NULL ) 00246 return false; 00247 // FIXME: memfile->GetLength() isn't the same as pFile->GetLength() in OnRenderFileData 00248 00249 // copy 00250 CFile file; 00251 if( file.Open(filename, CFile::modeCreate | CFile::modeWrite | CFile::typeBinary) == 0 ) 00252 return false; 00253 00254 wchar_t buff[10240]; 00255 UINT c; 00256 do 00257 { 00258 c = memfile->Read(buff, sizeof(buff)); 00259 00260 c = wcsnlen(buff, c/sizeof(wchar_t)) * sizeof(wchar_t); 00261 00262 file.Write(buff, c); 00263 } while( c == sizeof(buff) ); 00264 file.Close(); 00265 00266 // clear the memory file 00267 delete memfile; 00268 00269 // parse 00270 CComPtr<IMgaParser> parser; 00271 COMTHROW( parser.CoCreateInstance(L"Mga.MgaParser") ); 00272 ASSERT( parser != NULL ); 00273 00274 CComBstrObj acckind, version; 00275 VARIANT_BOOL is_acc_target; 00276 COMTHROW( parser->GetClipXMLInfo( PutInBstr(filename), target, &is_acc_target, PutOut( acckind), PutOut( version)) ); 00277 CString ver = _T("0"); // defval 00278 if( version) // clipboard main token found, otherwise use defval 00279 CopyTo( version, ver); 00280 00281 00282 CComObjPtr<IMgaProject> t_project; 00283 COMTHROW(target->get_Project( PutOut(t_project))); 00284 CComPtr<IGMEOLEApp> t_GME = CGMEDataSource::get_GME( t_project); 00285 00286 CComBSTR msg, done; 00287 COMTHROW(done.Append(_T("Done."))); 00288 if( ver == _T("0")) 00289 { 00290 COMTHROW(msg.Append(_T("Inserting XML data..."))); 00291 if( t_GME) COMTHROW( t_GME->ConsoleMessage( msg, MSG_INFO)); 00292 COMTHROW( parser->ParseFCOs(target, PutInBstr(filename)) ); 00293 if( t_GME) COMTHROW( t_GME->ConsoleMessage( done, MSG_INFO)); 00294 } 00295 else if( ver == _T("4")) 00296 { 00297 COMTHROW(msg.Append(_T("Inserting XML SmartCopied data..."))); 00298 if( t_GME) COMTHROW( t_GME->ConsoleMessage( msg, MSG_INFO)); 00299 COMTHROW( parser->ParseClos4( target, PutInBstr(filename), merge?MERGE:ADDITION )); 00300 if( t_GME) COMTHROW( t_GME->ConsoleMessage( done, MSG_INFO)); 00301 } 00302 else if ( ver == _T("1") || ver == _T("")) 00303 { 00304 COMTHROW(msg.Append(_T("Inserting XML CopyClosured data..."))); 00305 if( t_GME) COMTHROW( t_GME->ConsoleMessage( msg, MSG_INFO)); 00306 COMTHROW( parser->ParseClos1(target, PutInBstr(filename)) ); 00307 if( t_GME) COMTHROW( t_GME->ConsoleMessage( done, MSG_INFO)); 00308 } 00309 else 00310 { 00311 COMTHROW(msg.Append(_T("Error: Unknown clipboard closure format"))); 00312 if( t_GME) COMTHROW( t_GME->ConsoleMessage( msg, MSG_INFO)); 00313 00314 ASSERT(0); 00315 } 00316 00317 00318 CFile::Remove(filename); 00319 00320 return true; 00321 } 00322 catch(hresult_exception &e) 00323 { 00324 CFile::Remove(filename); 00325 00326 try 00327 { 00328 CComObjPtr<IErrorInfo> errinfo; 00329 COMTHROW( GetErrorInfo(0, PutOut(errinfo)) ); 00330 ASSERT( errinfo != NULL ); 00331 00332 CString desc; 00333 COMTHROW( errinfo->GetDescription(PutOut(desc)) ); 00334 00335 AfxMessageBox(CString(_T("Error while parsing XML file: ")) + desc); 00336 } 00337 catch(hresult_exception &) 00338 { 00339 AfxMessageBox(_T("Fatal error while parsing XML file!")); 00340 } 00341 00342 throw e; 00343 } 00344 00345 return false; 00346 } 00347 00348 void CGMEDataSource::CacheDescriptor(CGMEDataDescriptor* desc) 00349 { 00350 CacheGlobalData(cfGMEDesc, CreateDescriptor(desc)); 00351 DelayXMLDump(); 00352 } 00353 00354 HGLOBAL CGMEDataSource::CreateDescriptor(CGMEDataDescriptor* desc) 00355 { 00356 ASSERT(desc); 00357 00358 CSharedFile file; 00359 CArchive ar(&file, CArchive::store); 00360 desc->Serialize(ar); 00361 ar.Close(); 00362 return file.Detach(); 00363 } 00364 00365 void CGMEDataSource::DelayXMLDump() 00366 { 00367 FORMATETC fe = { 00368 CF_UNICODETEXT, NULL, DVASPECT_CONTENT, -1, TYMED_ISTREAM|TYMED_HGLOBAL 00369 }; 00370 00371 DelayRenderFileData(CF_UNICODETEXT, &fe); 00372 } 00373 00374 BOOL CGMEDataSource::OnRenderFileData(LPFORMATETC lpFormatEtc, CFile* pFile) 00375 { 00376 if( lpFormatEtc->cfFormat == CF_UNICODETEXT ) 00377 { 00378 ASSERT( pFile != NULL ); 00379 00380 // TODO: we have to dump it directly to the shared memory file 00381 00382 try 00383 { 00384 TCHAR *fname = _ttempnam(_T("c:\\temp"), _T("tmp")); 00385 CString filename = fname; 00386 free(fname); 00387 00388 CComPtr<IMgaDumper> dumper; 00389 COMTHROW( dumper.CoCreateInstance(L"Mga.MgaDumper") ); 00390 00391 CComObjPtr<IMgaFCOs> fcos; 00392 if ( data) // check whether it is set 00393 COMTHROW( ::QueryInterface( data, fcos) ); 00394 00395 CComObjPtr<IMgaFolders> folds; 00396 if ( folders) // check whether it is set 00397 COMTHROW( ::QueryInterface( folders, folds) ); 00398 00399 CComObjPtr<IMgaRegNodes> regd; 00400 if ( regdata) // check whether it is set 00401 COMTHROW( ::QueryInterface( regdata, regd) ); 00402 00403 COMTHROW( dumper->DumpFCOs( project, fcos, folds, regd, PutInBstr(filename)) ); 00404 00405 CFile file; 00406 if( file.Open(filename, CFile::modeRead | CFile::typeBinary) == 0 ) 00407 return FALSE; 00408 00409 const int buffsize = 10240; 00410 unsigned char buff[buffsize]; 00411 file.Read(buff, 2); // skip BOM 00412 UINT c; 00413 do 00414 { 00415 c = file.Read(buff, buffsize); 00416 pFile->Write(buff, c); 00417 } while( c == buffsize ); 00418 pFile->Write(L"", sizeof(wchar_t)); 00419 00420 file.Close(); 00421 CFile::Remove(filename); 00422 } 00423 catch(hresult_exception &) 00424 { 00425 return FALSE; 00426 } 00427 catch(CFileException *) 00428 { 00429 return FALSE; 00430 } 00431 00432 return TRUE; 00433 } 00434 00435 return FALSE; 00436 } 00437 00438 // **************************************************************************************************** 00439 // ********************************* CGMEClosureDataSource ***************************************** 00440 // **************************************************************************************************** 00441 BOOL CGMEClosureDataSource::OnRenderFileData(LPFORMATETC lpFormatEtc, CFile* pFile) 00442 { 00443 if( lpFormatEtc->cfFormat == CF_UNICODETEXT ) 00444 { 00445 ASSERT( pFile != NULL ); 00446 00447 // TODO: we have to dump it directly to the shared memory file 00448 00449 try 00450 { 00451 TCHAR *fname = _ttempnam(_T("c:\\temp"), _T("tmp")); 00452 CString filename = fname; 00453 free(fname); 00454 00455 CComPtr<IMgaDumper> dumper; 00456 COMTHROW( dumper.CoCreateInstance(L"Mga.MgaDumper") ); 00457 00458 CComObjPtr<IMgaFCOs> fcos; 00459 if ( data) // is it set? 00460 COMTHROW( ::QueryInterface(data, fcos) ); 00461 00462 CComObjPtr<IMgaFolders> fols; 00463 if ( folders) // is it set? 00464 COMTHROW( ::QueryInterface( folders, fols) ); 00465 00466 bool is_top_set = false; 00467 CComObjPtr<IMgaFCOs> top_fcos; 00468 CComObjPtr<IMgaFolders> top_folds; 00469 00470 if ( m_topFcos) 00471 { 00472 COMTHROW( ::QueryInterface( m_topFcos, top_fcos) ); 00473 is_top_set = true; 00474 } 00475 00476 if ( m_topFolders) 00477 { 00478 COMTHROW( ::QueryInterface( m_topFolders, top_folds) ); 00479 is_top_set = true; 00480 } 00481 00482 if ( is_top_set) 00483 COMTHROW( dumper->DumpClosR( fcos, fols, PutInBstr( filename), top_fcos, top_folds, m_options, m_absPathPart, m_acceptingKinds) ); 00484 else // if top objects are not set dump starting from RootFolder 00485 COMTHROW( dumper->DumpClos( fcos, fols, PutInBstr( filename), m_options) ); 00486 00487 CFile file; 00488 if( file.Open(filename, CFile::modeRead | CFile::typeBinary) == 0 ) 00489 return FALSE; 00490 00491 const int buffsize = 10240; 00492 unsigned char buff[buffsize]; 00493 UINT c; 00494 do 00495 { 00496 c = file.Read(buff, buffsize); 00497 pFile->Write(buff, c); 00498 } while( c == buffsize ); 00499 00500 pFile->Write(L"", sizeof(wchar_t)); 00501 00502 file.Close(); 00503 CFile::Remove(filename); 00504 } 00505 catch(hresult_exception &) 00506 { 00507 return FALSE; 00508 } 00509 catch(CFileException *) 00510 { 00511 return FALSE; 00512 } 00513 00514 return TRUE; 00515 } 00516 00517 return FALSE; 00518 } 00519 00520 BEGIN_MESSAGE_MAP(CGMEDataSource, COleDataSource) 00521 //{{AFX_MSG_MAP(CGMEDataSource) 00522 // NOTE - the ClassWizard will add and remove mapping macros here. 00523 //}}AFX_MSG_MAP 00524 END_MESSAGE_MAP() 00525 00526 // Interface Maps 00527 00528 BEGIN_DISPATCH_MAP(CGMEDataSource, COleDataSource) 00529 //{{AFX_DISPATCH_MAP(CGMEDataSource) 00530 DISP_PROPERTY_EX(CGMEDataSource, "Data", DispGetData, DispSetData, VT_DISPATCH) 00531 DISP_PROPERTY_EX(CGMEDataSource, "Folders", DispGetFolders, DispSetFolders, VT_DISPATCH) 00532 DISP_PROPERTY_EX(CGMEDataSource, "RegistryData", DispGetRegistryData, DispSetRegistryData, VT_DISPATCH) 00533 DISP_PROPERTY_EX(CGMEDataSource, "Project", DispGetProject, DispSetProject, VT_DISPATCH) 00534 //}}AFX_DISPATCH_MAP 00535 END_DISPATCH_MAP() 00536 00537 00538 BEGIN_INTERFACE_MAP(CGMEDataSource, COleDataSource) 00539 INTERFACE_PART(CGMEDataSource, IID_IMgaDataSource, MgaDataSource) 00540 DUAL_ERRORINFO_PART(CGMEDataSource) 00541 END_INTERFACE_MAP() 00542 00543 DELEGATE_DUAL_INTERFACE(CGMEDataSource, MgaDataSource) 00544 00545 // Implement ISupportErrorInfo to indicate we support the 00546 // OLE Automation error handler. 00547 IMPLEMENT_DUAL_ERRORINFO(CGMEDataSource, IID_IMgaDataSource) 00548 00549 00550 STDMETHODIMP CGMEDataSource::XMgaDataSource::get_Data(IUnknown **p) 00551 { 00552 METHOD_PROLOGUE(CGMEDataSource, MgaDataSource) 00553 CHECK_OUT(p); 00554 00555 if( pThis->data != NULL ) 00556 return pThis->data.QueryInterface(p); 00557 00558 return S_OK; 00559 } 00560 00561 STDMETHODIMP CGMEDataSource::XMgaDataSource::get_Folders(IUnknown **p) 00562 { 00563 METHOD_PROLOGUE(CGMEDataSource, MgaDataSource) 00564 CHECK_OUT(p); 00565 00566 if( pThis->folders != NULL ) 00567 return pThis->folders.QueryInterface(p); 00568 00569 return S_OK; 00570 } 00571 00572 STDMETHODIMP CGMEDataSource::XMgaDataSource::get_RegistryData(IUnknown **p) 00573 { 00574 METHOD_PROLOGUE(CGMEDataSource, MgaDataSource) 00575 CHECK_OUT(p); 00576 00577 if( pThis->regdata != NULL ) 00578 return pThis->regdata.QueryInterface(p); 00579 00580 return S_OK; 00581 } 00582 00583 STDMETHODIMP CGMEDataSource::XMgaDataSource::get_Project(IUnknown **p) 00584 { 00585 METHOD_PROLOGUE(CGMEDataSource, MgaDataSource) 00586 CHECK_OUT(p); 00587 00588 return pThis->project.QueryInterface(p); 00589 } 00590 00591 00592 00593 00594 /*static*/ CComPtr<IGMEOLEApp> CGMEDataSource::get_GME(CComObjPtr<IMgaProject> project) 00595 { 00596 CComPtr<IGMEOLEApp> gme; 00597 if ( (project != NULL)) { 00598 CComBSTR bstrName(L"GME.Application"); 00599 CComPtr<IMgaClient> pClient; 00600 HRESULT hr = project->GetClientByName(bstrName, &pClient); 00601 if (SUCCEEDED(hr) && pClient) { 00602 CComPtr<IDispatch> pDispatch; 00603 hr = pClient->get_OLEServer(&pDispatch); 00604 if (SUCCEEDED(hr) && pDispatch) { 00605 hr = pDispatch.QueryInterface(&gme); 00606 if (FAILED(hr)) { 00607 gme = NULL; 00608 } 00609 } 00610 } 00611 } 00612 return gme; 00613 } 00614 00615 LPDISPATCH CGMEDataSource::DispGetData() 00616 { 00617 CComPtr<IDispatch> p; 00618 if( data != NULL ) { 00619 data.QueryInterface(&p); 00620 } 00621 00622 return p.Detach(); 00623 } 00624 00625 void CGMEDataSource::DispSetData(LPDISPATCH) 00626 { 00627 SetNotSupported(); 00628 } 00629 00630 LPDISPATCH CGMEDataSource::DispGetFolders() 00631 { 00632 CComPtr<IDispatch> p; 00633 if( folders != NULL ) { 00634 folders.QueryInterface(&p); 00635 } 00636 00637 return p.Detach(); 00638 } 00639 00640 void CGMEDataSource::DispSetFolders(LPDISPATCH) 00641 { 00642 SetNotSupported(); 00643 } 00644 00645 LPDISPATCH CGMEDataSource::DispGetRegistryData() 00646 { 00647 CComPtr<IDispatch> p; 00648 if( regdata != NULL ) { 00649 regdata.QueryInterface(&p); 00650 } 00651 00652 return p.Detach(); 00653 } 00654 00655 void CGMEDataSource::DispSetRegistryData(LPDISPATCH) 00656 { 00657 SetNotSupported(); 00658 } 00659 00660 LPDISPATCH CGMEDataSource::DispGetProject() 00661 { 00662 CComPtr<IDispatch> p; 00663 if( project != NULL ) { 00664 COMTHROW(project.QueryInterface(&p)); 00665 } 00666 00667 return p.Detach(); 00668 } 00669 00670 void CGMEDataSource::DispSetProject(LPDISPATCH) 00671 { 00672 SetNotSupported(); 00673 } 00674 00675