Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

889 lines
24 KiB

  1. /******************************************************************************
  2. * Temp conversion utility to take registry entries and populate the class store with those entries.
  3. *****************************************************************************/
  4. /******************************************************************************
  5. includes
  6. ******************************************************************************/
  7. #include "precomp.hxx"
  8. #include "..\appmgr\resource.h"
  9. extern HINSTANCE ghInstance;
  10. #define WTOA(sz, wsz, cch) WideCharToMultiByte(CP_ACP, 0, wsz, -1, sz, cch, NULL, NULL)
  11. #define HOME 1
  12. /******************************************************************************
  13. defines and prototypes
  14. ******************************************************************************/
  15. extern CLSID CLSID_ClassStore;
  16. extern const IID IID_IClassAdmin;
  17. CLSID CLSID_ClassStore = { /* 62392950-1AF8-11d0-B267-00A0C90F56FC */
  18. 0x62392950,
  19. 0x1af8,
  20. 0x11d0,
  21. {0xb2, 0x67, 0x00, 0xa0, 0xc9, 0x0f, 0x56, 0xfc}
  22. };
  23. const IID IID_IClassStore = {
  24. 0x00000190,
  25. 0x0000,
  26. 0x0000,
  27. {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}
  28. };
  29. const IID IID_IClassAdmin = {
  30. 0x00000191,
  31. 0x0000,
  32. 0x0000,
  33. {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}
  34. };
  35. int
  36. CompareClassDetails(
  37. CLASSDETAIL * p1,
  38. CLASSDETAIL * p2 );
  39. HRESULT
  40. UpdateDatabaseFromRegistry(
  41. MESSAGE * pMessage );
  42. HRESULT
  43. UpdateClassStoreFromDatabase(
  44. MESSAGE * pMessage,
  45. IClassAdmin * pClassAdmin );
  46. HRESULT
  47. UpdateClassStoreFromMessage(
  48. MESSAGE * pMessage,
  49. IClassAdmin * pClassAdmin );
  50. HRESULT
  51. UpdateClassAssociations(
  52. MESSAGE * pMessage,
  53. IClassAdmin * pClassAdmin );
  54. void
  55. RemoveClassAssociations(
  56. MESSAGE * pMessage,
  57. IClassAdmin * pClassAdmin );
  58. HRESULT
  59. UpdatePackageDetails(
  60. MESSAGE * pMessage,
  61. IClassAdmin * pClassAdmin );
  62. void
  63. RemoveOneClassAssociation(
  64. MESSAGE * pMessage,
  65. CLASS_ENTRY * pClsEntry,
  66. IClassAdmin * pClassAdmin );
  67. HRESULT
  68. UpdateOneClassAssociation(
  69. MESSAGE * pMessage,
  70. CLASS_ENTRY * pClsEntry,
  71. IClassAdmin * pClassAdmin );
  72. HRESULT
  73. UpdateOnePackageDetail(
  74. MESSAGE * pMessage,
  75. PACKAGE_ENTRY * pClsEntry,
  76. IClassAdmin * pClassAdmin );
  77. LONG
  78. UpdateDatabaseFromTypelib(
  79. MESSAGE * pMessage );
  80. void
  81. DumpTypelibEntries(
  82. MESSAGE * pMessage );
  83. LONG
  84. UpdateDatabaseFromFileExt(
  85. MESSAGE * pMessage );
  86. LONG
  87. UpdateDatabaseFromProgID(
  88. MESSAGE * pMessage );
  89. LONG
  90. UpdateDatabaseFromIID(
  91. MESSAGE * pMessage );
  92. HRESULT
  93. AddToClassStore(
  94. MESSAGE *pMessage,
  95. IClassAdmin * pClassAdmin );
  96. void
  97. AppEntryToAppDetail(
  98. APP_ENTRY * pAppEntry,
  99. APPDETAIL * pAppDetail );
  100. HRESULT
  101. UpdatePackageDetails(
  102. MESSAGE * pMessage,
  103. IClassAdmin * pClassAdmin );
  104. void
  105. AppEntryToAppDetail(
  106. APP_ENTRY * pAppEntry,
  107. APPDETAIL * pAppDetail );
  108. HRESULT
  109. UpdateInterfaceEntries(
  110. MESSAGE * pMessage,
  111. IClassAdmin * pClassAdmin );
  112. HRESULT
  113. UpdateOneInterfaceEntry(
  114. MESSAGE * pMessage,
  115. ITF_ENTRY * pITFEntry,
  116. IClassAdmin * pClassAdmin );
  117. /******************************************************************************
  118. Da Code
  119. ******************************************************************************/
  120. HRESULT
  121. VerifyArguments( MESSAGE * pMessage )
  122. {
  123. // if( !pMessage->pRegistryKeyName )
  124. // return MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, ERROR_INVALID_PARAMETER );
  125. return S_OK;
  126. }
  127. HRESULT
  128. UpdateDatabaseFromRegistry(
  129. MESSAGE * pMessage )
  130. {
  131. HRESULT hr = S_OK;
  132. hr = HRESULT_FROM_WIN32( UpdateDatabaseFromCLSID( pMessage ));
  133. if ( HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr )
  134. return UpdateDatabaseFromFileExt(pMessage);
  135. if ( !SUCCEEDED(hr ) )
  136. return hr;
  137. hr = HRESULT_FROM_WIN32( UpdateDatabaseFromFileExt( pMessage ));
  138. if ( !SUCCEEDED(hr ) )
  139. return hr;
  140. hr = HRESULT_FROM_WIN32( UpdateDatabaseFromProgID( pMessage ));
  141. if ( !SUCCEEDED(hr ) )
  142. return hr;
  143. hr = HRESULT_FROM_WIN32( UpdateDatabaseFromIID( pMessage ));
  144. if ( !SUCCEEDED(hr ) )
  145. return hr;
  146. hr = HRESULT_FROM_WIN32( UpdateDatabaseFromTypelib( pMessage ));
  147. if ( !SUCCEEDED(hr ) )
  148. return hr;
  149. return hr;
  150. }
  151. HRESULT
  152. UpdateClassStoreFromDatabase( MESSAGE * pMessage, IClassAdmin * pClassAdmin )
  153. {
  154. HRESULT hr;
  155. hr = UpdateClassAssociations( pMessage, pClassAdmin );
  156. if ( SUCCEEDED(hr))
  157. {
  158. hr = UpdateInterfaceEntries( pMessage, pClassAdmin );
  159. if ( SUCCEEDED(hr) )
  160. {
  161. hr = UpdatePackageDetails( pMessage, pClassAdmin );
  162. }
  163. }
  164. if (FAILED(hr))
  165. {
  166. // We blew it somewhere so we need to remove all the CLSIDs that we
  167. // might have added.
  168. RemoveClassAssociations( pMessage, pClassAdmin);
  169. }
  170. return hr;
  171. }
  172. HRESULT
  173. UpdateClassStoreFromMessage( MESSAGE * pMessage, IClassAdmin * pClassAdmin )
  174. {
  175. HRESULT hr;
  176. if ( (hr = VerifyArguments( pMessage )) == S_OK )
  177. {
  178. hr = UpdateDatabaseFromRegistry( pMessage );
  179. if (SUCCEEDED(hr) || MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32,ERROR_NO_MORE_ITEMS) == hr)
  180. {
  181. if (pMessage->hRoot != HKEY_CLASSES_ROOT)
  182. {
  183. // We mapped it into a temporary key so we need to do a pass
  184. // on HKEY_CLASSES_ROOT as well in order to catch anything
  185. // that might have been copied there instead of into our
  186. // remapped key.
  187. // This is a problem because we can't remap HKCR across
  188. // process boundaries, our remapping function only works in
  189. // this process.
  190. pMessage->hRoot = HKEY_CLASSES_ROOT;
  191. hr = UpdateDatabaseFromRegistry( pMessage );
  192. }
  193. if (SUCCEEDED(hr) || MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32,ERROR_NO_MORE_ITEMS) == hr)
  194. {
  195. hr = UpdateClassStoreFromDatabase( pMessage, pClassAdmin );
  196. }
  197. }
  198. }
  199. return hr;
  200. }
  201. HRESULT
  202. UpdateInterfaceEntries(
  203. MESSAGE * pMessage,
  204. IClassAdmin * pClassAdmin )
  205. {
  206. ITF_ENTRY * pITFEntry = (ITF_ENTRY *)pMessage->pIIDict->GetFirst();
  207. HRESULT hr;
  208. if ( pITFEntry )
  209. {
  210. do
  211. {
  212. hr = UpdateOneInterfaceEntry(pMessage,pITFEntry,pClassAdmin);
  213. if ( !SUCCEEDED(hr) )
  214. return hr;
  215. pITFEntry = pMessage->pIIDict->GetNext( pITFEntry );
  216. } while ( pITFEntry != 0 );
  217. }
  218. else
  219. hr = MAKE_HRESULT( SEVERITY_SUCCESS, 0, 1 ); // no interfaces.
  220. return hr;
  221. }
  222. HRESULT
  223. UpdateOneInterfaceEntry(
  224. MESSAGE * pMessage,
  225. ITF_ENTRY * pITFEntry,
  226. IClassAdmin * pClassAdmin )
  227. {
  228. CLSID IID;
  229. CLSID PSClsid;
  230. CLSID TypelibID;
  231. StringToCLSID( &pITFEntry->IID[1], &IID );
  232. StringToCLSID( &pITFEntry->Clsid[1], &PSClsid );
  233. StringToCLSID( &pITFEntry->TypelibID[1], &PSClsid );
  234. HRESULT hr = S_OK;
  235. if ( !pMessage->fDumpOnly )
  236. hr = pClassAdmin->NewInterface( IID, L"", PSClsid, TypelibID );
  237. if (hr == HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS))
  238. hr = S_OK;
  239. return hr;
  240. }
  241. HRESULT
  242. UpdatePackageDetails(
  243. MESSAGE * pMessage,
  244. IClassAdmin * pClassAdmin )
  245. {
  246. PACKAGE_ENTRY * pPackageEntry =
  247. (PACKAGE_ENTRY *)pMessage->pPackageDict->GetFirst();
  248. HRESULT hr = S_OK;
  249. hr = E_FAIL;
  250. if ( pPackageEntry )
  251. {
  252. do
  253. {
  254. hr = UpdateOnePackageDetail(pMessage,pPackageEntry,pClassAdmin);
  255. if (!SUCCEEDED(hr))
  256. return hr;
  257. pPackageEntry = pMessage->pPackageDict->GetNext(pPackageEntry);
  258. } while ( pPackageEntry != 0 );
  259. }
  260. else
  261. hr = MAKE_HRESULT( SEVERITY_SUCCESS, 0, 1 ); // no packages.
  262. return hr;
  263. }
  264. HRESULT
  265. UpdateOnePackageDetail(
  266. MESSAGE * pMessage,
  267. PACKAGE_ENTRY * pPackageEntry,
  268. IClassAdmin * pClassAdmin )
  269. {
  270. PACKAGEDETAIL PackageDetail;
  271. APP_ENTRY *pAppEntry;
  272. int len;
  273. int count;
  274. HRESULT hr = S_OK;
  275. int Index = 0;
  276. int max;
  277. // copy the bare package details
  278. memcpy( &PackageDetail,
  279. &pPackageEntry->PackageDetails,
  280. sizeof( PACKAGEDETAIL ) );
  281. count = PackageDetail.cApps = pPackageEntry->Count;
  282. // if the null appid contains at least one clsid entry or typelib entry
  283. // assume one more app id in the package. There can be either a clsid entry or
  284. // a typelib entry in the null appid.
  285. if ( (pPackageEntry->GetCountOfClsidsInNullAppid() > 0 ) ||
  286. (pPackageEntry->GetCountOfTypelibsInNullAppid() > 0 )
  287. )
  288. {
  289. PackageDetail.cApps += 1;
  290. count++;
  291. }
  292. // Allocate an APPDETAIL structure if there is at least one appid in the
  293. // package.
  294. if ( count )
  295. {
  296. PackageDetail.pAppDetail = new APPDETAIL[ count ];
  297. memset( PackageDetail.pAppDetail, '\0', count * sizeof(APPDETAIL) );
  298. }
  299. // update the rest of entries that have an appid.
  300. for ( Index = 0, pAppEntry = pPackageEntry->pAppDict->GetFirst();
  301. pAppEntry && (Index < pPackageEntry->Count);
  302. ++Index, pAppEntry = pPackageEntry->pAppDict->GetNext( pAppEntry) )
  303. {
  304. AppEntryToAppDetail(pAppEntry, &PackageDetail.pAppDetail[ Index ] );
  305. }
  306. //
  307. // If there is at least one clsid in the null appid, then assign the appid
  308. // the same guid as the first clsid in the list. Else, if there is at least
  309. // one typelib in the list, assign the appid the same guid as the typelib id
  310. //
  311. if ( (max = pPackageEntry->GetCountOfClsidsInNullAppid()) > 0 )
  312. {
  313. APP_ENTRY A;
  314. char * p = pPackageEntry->GetFirstClsidInNullAppidList();
  315. A.SetAppIDString( p );
  316. // Add the Class ids from the NUll app entry list to the app entry..
  317. for ( count = 0, p = pPackageEntry->ClsidsInNullAppid->GetFirst();
  318. p && (count < max);
  319. ++count, p = pPackageEntry->ClsidsInNullAppid->GetNext( p )
  320. )
  321. {
  322. A.AddClsid( p );
  323. }
  324. // update the entries with the null clsid.
  325. AppEntryToAppDetail( &A, &PackageDetail.pAppDetail [ Index ] );
  326. // Add remote server names to app entry ( not implemented yet ).
  327. }
  328. else if ( (max = pPackageEntry->GetCountOfTypelibsInNullAppid()) > 0 )
  329. {
  330. APP_ENTRY A;
  331. char * p = pPackageEntry->GetFirstTypelibInNullAppidList();
  332. A.SetAppIDString( p );
  333. // Add the Class ids from the NUll app entry list to the app entry..
  334. for ( count = 0, p = pPackageEntry->TypelibsInNullAppid->GetFirst();
  335. p && (count < max);
  336. ++count, p = pPackageEntry->TypelibsInNullAppid->GetNext( p )
  337. )
  338. {
  339. A.AddTypelib( p );
  340. }
  341. // update the entries with the null clsid.
  342. AppEntryToAppDetail( &A, &PackageDetail.pAppDetail [ Index ] );
  343. }
  344. // update package name.
  345. len = strlen( &pPackageEntry->PackageName[0] );
  346. PackageDetail.pszPackageName = new OLECHAR[ (len +1 )*2 ];
  347. mbstowcs(PackageDetail.pszPackageName,&pPackageEntry->PackageName[0],len+1);
  348. // write the class store.
  349. if ( pMessage->fDumpOnly)
  350. {
  351. (*pMessage->pDumpOnePackage)( pMessage, &PackageDetail );
  352. hr = S_OK;
  353. }
  354. else
  355. hr = pClassAdmin->NewPackage( &PackageDetail );
  356. return hr;
  357. }
  358. void
  359. RemoveClassAssociations(
  360. MESSAGE * pMessage,
  361. IClassAdmin * pClassAdmin )
  362. {
  363. CLASS_ENTRY * pClsEntry = pMessage->pClsDict->GetFirst();
  364. if ( pClsEntry )
  365. {
  366. do
  367. {
  368. RemoveOneClassAssociation( pMessage, pClsEntry, pClassAdmin );
  369. pClsEntry = pMessage->pClsDict->GetNext( pClsEntry );
  370. } while ( pClsEntry != 0 );
  371. }
  372. }
  373. void
  374. RemoveOneClassAssociation(
  375. MESSAGE * pMessage,
  376. CLASS_ENTRY * pClsEntry,
  377. IClassAdmin * pClassAdmin )
  378. {
  379. CLSID clsid;
  380. StringToCLSID(&(pClsEntry->GetClsidString())[1], &clsid );
  381. pClassAdmin->DeleteClass( clsid );
  382. }
  383. HRESULT
  384. UpdateClassAssociations(
  385. MESSAGE * pMessage,
  386. IClassAdmin * pClassAdmin )
  387. {
  388. CLASS_ENTRY * pClsEntry = pMessage->pClsDict->GetFirst();
  389. HRESULT hr = S_OK;
  390. if ( pClsEntry )
  391. {
  392. do
  393. {
  394. hr = UpdateOneClassAssociation( pMessage, pClsEntry, pClassAdmin );
  395. if (hr != S_OK )
  396. return hr;
  397. pClsEntry = pMessage->pClsDict->GetNext( pClsEntry );
  398. } while ( pClsEntry != 0 );
  399. }
  400. return hr;
  401. }
  402. HRESULT
  403. UpdateOneClassAssociation(
  404. MESSAGE * pMessage,
  405. CLASS_ENTRY * pClsEntry,
  406. IClassAdmin * pClassAdmin )
  407. {
  408. CLASSASSOCIATION CA;
  409. LPOLESTR * prgFileExt;
  410. LPOLESTR * prgProgID;
  411. char * p;
  412. int len;
  413. ListEntry * pListEntry;
  414. HRESULT hr = S_OK;
  415. memcpy( &CA, &pClsEntry->ClassAssociation, sizeof( CLASSASSOCIATION ) );
  416. CA.cFileExt = pClsEntry->FileExtList.GetCount();
  417. CA.cOtherProgId = pClsEntry->OtherProgIDs.GetCount();
  418. // convert the classid into a guid
  419. StringToCLSID(&(pClsEntry->GetClsidString())[1], &CA.Clsid );
  420. // create the file extension array.
  421. if ( CA.cFileExt )
  422. {
  423. int count;
  424. // allocate array for the file extensions.
  425. CA.prgFileExt = prgFileExt = new LPOLESTR[ CA.cFileExt ];
  426. // copy the file extensions one by one.
  427. for ( count = 0, pListEntry = pClsEntry->FileExtList.GetFirst();
  428. pListEntry;
  429. ++count, pListEntry = pClsEntry->FileExtList.GetNext( pListEntry )
  430. )
  431. {
  432. char * p = (char *) pListEntry->pElement;
  433. int len = strlen(p);
  434. prgFileExt[ count ] = new OLECHAR[ (len+1)*2 ];
  435. mbstowcs( prgFileExt[ count ], p, len+1 );
  436. }
  437. }
  438. // create the progid array
  439. if ( CA.cOtherProgId )
  440. {
  441. int count;
  442. ListEntry * pListEntry;
  443. // allocate array for the file extensions.
  444. CA.prgOtherProgId = prgProgID = new LPOLESTR[ CA.cOtherProgId ];
  445. // copy the file extensions one by one.
  446. for ( count = 0, pListEntry = pClsEntry->OtherProgIDs.GetFirst();
  447. pListEntry;
  448. ++count, pListEntry = pClsEntry->OtherProgIDs.GetNext( pListEntry )
  449. )
  450. {
  451. p = (char *) pListEntry->pElement;
  452. len = strlen(p);
  453. prgProgID[ count ] = new OLECHAR[ (len +1) *2 ];
  454. mbstowcs( prgProgID[ count ], p, len+1 );
  455. }
  456. }
  457. // create the default progid - the first in the progidlist.
  458. if ( pClsEntry->OtherProgIDs.GetCount() )
  459. {
  460. pListEntry = pClsEntry->OtherProgIDs.GetFirst();
  461. p = (char *)pListEntry->pElement;
  462. len = strlen(p);
  463. CA.pDefaultProgId = new OLECHAR[ (len+1) * 2 ];
  464. mbstowcs( CA.pDefaultProgId, p, len+1 );
  465. }
  466. else
  467. CA.pDefaultProgId = 0;
  468. if (CA.pszDesc == NULL)
  469. {
  470. CA.pszDesc = L"";
  471. }
  472. if ( !pMessage->fDumpOnly )
  473. {
  474. // First try and delete the class entry to make sure this class ID
  475. // isn't orphaned from some earlier partial installation. If the
  476. // classid is in the class store but isn't listed as being
  477. // implemented by an application then this will cause it to be
  478. // deleted. If it _IS_ implemented by another application then this
  479. // wil be a NOP.
  480. pClassAdmin->DeleteClass(CA.Clsid);
  481. hr = pClassAdmin->NewClass( &CA );
  482. }
  483. if ( hr == HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) ) // duplicate
  484. {
  485. // Get details of the pre-existing class.
  486. CLASSDETAIL cdOld;
  487. hr = pClassAdmin->GetClassDetails(CA.Clsid, &cdOld);
  488. if (SUCCEEDED(hr))
  489. {
  490. // Check to see if they are equivalent (CompareClassDetails).
  491. int i = CompareClassDetails(&CA, &cdOld);
  492. if (0 != i)
  493. {
  494. // Inform the user of a conflict and abort
  495. TCHAR szCaption[256];
  496. TCHAR szBuffer[1024];
  497. ::LoadString(ghInstance, IDS_CLSIDCONFLICT1, szBuffer, 1024);
  498. // UNDONE - we need to get the other application's name here.
  499. strcpy(szCaption, "some other application");
  500. IEnumPackage * pIEP;
  501. CSPLATFORM cp;
  502. memset(&cp, 0, sizeof(cp));
  503. hr = pClassAdmin->GetPackagesEnum(CA.Clsid,
  504. NULL,
  505. cp,
  506. 0,
  507. 0,
  508. &pIEP);
  509. if (SUCCEEDED(hr))
  510. {
  511. ULONG ul;
  512. PACKAGEDETAIL pd;
  513. hr = pIEP->Next(1, &pd, &ul);
  514. if (SUCCEEDED(hr) && 1 == ul)
  515. {
  516. WTOA(szCaption, pd.pszPackageName, 256);
  517. }
  518. pIEP->Release();
  519. }
  520. strcat(szBuffer, szCaption);
  521. ::LoadString(ghInstance, IDS_CLSIDCONFLICT2, szCaption, 256);
  522. strcat (szBuffer, szCaption);
  523. strncpy(szCaption, pMessage->pPackagePath, 256);
  524. int iReturn = ::MessageBox(pMessage->hwnd, szBuffer,
  525. szCaption,
  526. MB_OK);
  527. hr = HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS);
  528. }
  529. else
  530. {
  531. // they aren't different so it's OK to continue
  532. hr = S_OK;
  533. }
  534. }
  535. }
  536. //
  537. // before return, update the class association data structure back to the class
  538. // entry structure, so that the dumper can use it.
  539. memcpy( &pClsEntry->ClassAssociation, &CA, sizeof( CLASSASSOCIATION ) );
  540. return hr;
  541. }
  542. // compares two class details
  543. //
  544. //
  545. // Input: p1: Pointer to a CLASSDETAIL structure
  546. // p2: Pointer to the other CLASSDETAIL structure
  547. // Returns:
  548. // 0 if all is well, -1 otherwise.
  549. // Notes: DOES NOT CHECK FOR NULL INPUT POINTERS.
  550. //
  551. int
  552. CompareClassDetails(
  553. CLASSDETAIL * p1,
  554. CLASSDETAIL * p2 )
  555. {
  556. // compare the class id.
  557. if( _memicmp( (const void * )&p1->Clsid,
  558. (const void *)&p2->Clsid,
  559. sizeof( CLSID ) ) )
  560. return -1;
  561. // We do not compare pszdesc, since it is just an info field.
  562. // We DO compare the icon paths, since if icon paths are different, they are
  563. // likely to be different packages supporting the same classid. (I am not
  564. // sure, this is a good argument)
  565. if( p1->pszIconPath && p2->pszIconPath )
  566. {
  567. if( _wcsicmp( (const wchar_t *)p1->pszIconPath,
  568. (const wchar_t *)p2->pszIconPath ) != 0 )
  569. return -1;
  570. }
  571. // test the Treatas and AutoConvert CLSIDs
  572. if( _memicmp( (const unsigned char *)&p1->TreatAsClsid,
  573. (const unsigned char *)&p2->TreatAsClsid,
  574. sizeof( CLSID ) ) )
  575. return -1;
  576. if( _memicmp( (const unsigned char *)&p1->AutoConvertClsid,
  577. (const unsigned char *)&p2->AutoConvertClsid,
  578. sizeof( CLSID ) ) )
  579. return -1;
  580. // If the count of file extensions do not match, they are likely different
  581. // packages.
  582. if( p1->cFileExt != p2->cFileExt )
  583. return -1;
  584. else
  585. {
  586. int i, cFileExt;
  587. // All the file extensions should match for the guaranteeing that the
  588. // package is the same.
  589. for( i = 0, cFileExt = p1->cFileExt;
  590. i < cFileExt;
  591. ++i
  592. )
  593. {
  594. if(_wcsicmp( (const wchar_t *)p1->prgFileExt[ i ],
  595. (const wchar_t *)p2->prgFileExt[ i ] ) != 0 )
  596. return -1;
  597. }
  598. if( i < cFileExt )
  599. return -1;
  600. }
  601. // compare mime type.
  602. if( p1->pMimeType && p2->pMimeType )
  603. {
  604. if( _wcsicmp( (const wchar_t *)p1->pMimeType,
  605. (const wchar_t *)p2->pMimeType ) != 0 )
  606. return -1;
  607. }
  608. // compare default progid.
  609. if( p1->pDefaultProgId && p2->pDefaultProgId )
  610. {
  611. if( _wcsicmp( (const wchar_t *)p1->pDefaultProgId,
  612. (const wchar_t *)p2->pDefaultProgId ) != 0 )
  613. return -1;
  614. }
  615. // if the count of Other prog ids do not match , they are likely different
  616. // packages
  617. if( p1->cOtherProgId != p2->cOtherProgId )
  618. return -1;
  619. else
  620. {
  621. int i, cOtherProgId;
  622. // All the OtherProgIds should match for the guaranteeing that the
  623. // package is the same.
  624. for( i = 0, cOtherProgId = p1->cOtherProgId;
  625. i < cOtherProgId;
  626. ++i
  627. )
  628. {
  629. if(_wcsicmp((const wchar_t *)p1->prgOtherProgId[ i ],
  630. (const wchar_t *)p2->prgOtherProgId[ i ]) != 0 )
  631. return -1;
  632. }
  633. if( i < cOtherProgId )
  634. return -1;
  635. }
  636. return 0;
  637. }
  638. void
  639. AppEntryToAppDetail(
  640. APP_ENTRY * pAppEntry,
  641. APPDETAIL * pAppDetail )
  642. {
  643. int count;
  644. ListEntry * pListEntry;
  645. char * p;
  646. StringToCLSID( &pAppEntry->AppIDString[1], &pAppDetail->AppID );
  647. // pick up the clsid list.
  648. if ( count = pAppEntry->ClsidList.GetCount() )
  649. {
  650. // Allocate space for requisite # of CLSIDs
  651. pAppDetail->cClasses = count;
  652. pAppDetail->prgClsIdList = new CLSID[ count ];
  653. for ( count = 0, pListEntry = pAppEntry->ClsidList.GetFirst();
  654. pListEntry;
  655. pListEntry = pAppEntry->ClsidList.GetNext( pListEntry ), ++count
  656. )
  657. {
  658. p = (char*)pListEntry->pElement;
  659. StringToCLSID( p+1, &pAppDetail->prgClsIdList[count] );
  660. }
  661. }
  662. // pick up typelib list.
  663. if ( count = pAppEntry->TypelibList.GetCount() )
  664. {
  665. // Allocate space for requisite # of Typelibs
  666. pAppDetail->cTypeLibIds = count;
  667. pAppDetail->prgTypeLibIdList = new CLSID[ count ];
  668. for ( count = 0, pListEntry = pAppEntry->TypelibList.GetFirst();
  669. pListEntry;
  670. pListEntry = pAppEntry->TypelibList.GetNext( pListEntry ), ++count
  671. )
  672. {
  673. p = (char*)pListEntry->pElement;
  674. StringToCLSID( p+1, &pAppDetail->prgTypeLibIdList[count] );
  675. }
  676. }
  677. // pick up remote server name list.
  678. if ( count = pAppEntry->RemoteServerNameList.GetCount() )
  679. {
  680. pAppDetail->prgServerNames = new LPOLESTR[ count ];
  681. pAppDetail->cServers = count;
  682. for ( count = 0, pListEntry = pAppEntry->RemoteServerNameList.GetFirst();
  683. pListEntry;
  684. pListEntry = pAppEntry->RemoteServerNameList.GetNext( pListEntry ), ++count
  685. )
  686. {
  687. p = (char *) pListEntry->pElement;
  688. int len = strlen(p);
  689. pAppDetail->prgServerNames[ count ] = new OLECHAR[ (len +1) * 2 ];
  690. mbstowcs( pAppDetail->prgServerNames[count], p, len+1 );
  691. }
  692. }
  693. }
  694. HRESULT
  695. AddToClassStore( MESSAGE *pMessage, IClassAdmin * pClassAdmin )
  696. {
  697. return S_OK;
  698. }