Changeset 8620 for trunk/src/ole32/storage32.c
- Timestamp:
- Jun 9, 2002, 6:37:22 PM (23 years ago)
- File:
-
- 1 edited
-
trunk/src/ole32/storage32.c (modified) (282 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/ole32/storage32.c
r8441 r8620 24 24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 25 25 */ 26 27 26 #ifdef __WIN32OS2__ 28 27 #include "ole32.h" … … 60 59 /* OLESTREAM memory structure to use for Get and Put Routines */ 61 60 /* Used for OleConvertIStorageToOLESTREAM and OleConvertOLESTREAMToIStorage */ 62 typedef struct 61 typedef struct 63 62 { 64 63 DWORD dwOleID; … … 98 97 DWORD dwExtentX; 99 98 DWORD dwExtentY; 100 DWORD dwSize; 99 DWORD dwSize; 101 100 BYTE *pData; 102 101 }OLECONVERT_ISTORAGE_OLEPRES; … … 123 122 INT typeOfRelation); 124 123 125 static HRESULT adjustPropertyChain( 124 static HRESULT adjustPropertyChain( 126 125 StorageImpl *This, 127 126 StgProperty propertyToDelete, … … 150 149 * Declaration of miscellaneous functions... 151 150 */ 152 static HRESULT validateSTGM(DWORD stgmValue); 151 static HRESULT validateSTGM(DWORD stgmValue); 153 152 154 153 static DWORD GetShareModeFromSTGM(DWORD stgm); … … 236 235 * This method implements the common QueryInterface for all IStorage32 237 236 * implementations contained in this file. 238 * 237 * 239 238 * See Windows documentation for more details on IUnknown methods. 240 239 */ … … 250 249 if ( (This==0) || (ppvObject==0) ) 251 250 return E_INVALIDARG; 252 251 253 252 /* 254 253 * Initialize the return parameter. 255 254 */ 256 255 *ppvObject = 0; 257 256 258 257 /* 259 258 * Compare the riid with the interface IDs implemented by this object. 260 259 */ 261 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0) 260 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0) 262 261 { 263 262 *ppvObject = (IStorage*)This; 264 263 } 265 else if (memcmp(&IID_IStorage, riid, sizeof(IID_IStorage)) == 0) 264 else if (memcmp(&IID_IStorage, riid, sizeof(IID_IStorage)) == 0) 266 265 { 267 266 *ppvObject = (IStorage*)This; 268 267 } 269 268 270 269 /* 271 270 * Check that we obtained an interface. … … 273 272 if ((*ppvObject)==0) 274 273 return E_NOINTERFACE; 275 274 276 275 /* 277 276 * Query Interface always increases the reference count by one when it is … … 282 281 return S_OK; 283 282 } 284 283 285 284 /************************************************************************ 286 285 * Storage32BaseImpl_AddRef (IUnknown) … … 288 287 * This method implements the common AddRef for all IStorage32 289 288 * implementations contained in this file. 290 * 289 * 291 290 * See Windows documentation for more details on IUnknown methods. 292 291 */ 293 ULONG WINAPI StorageBaseImpl_AddRef( 292 ULONG WINAPI StorageBaseImpl_AddRef( 294 293 IStorage* iface) 295 294 { … … 299 298 return This->ref; 300 299 } 301 300 302 301 /************************************************************************ 303 302 * Storage32BaseImpl_Release (IUnknown) … … 305 304 * This method implements the common Release for all IStorage32 306 305 * implementations contained in this file. 307 * 306 * 308 307 * See Windows documentation for more details on IUnknown methods. 309 308 */ 310 ULONG WINAPI StorageBaseImpl_Release( 309 ULONG WINAPI StorageBaseImpl_Release( 311 310 IStorage* iface) 312 311 { … … 323 322 { 324 323 /* 325 * Since we are using a system of base-classes, we want to call the 326 * destructor of the appropriate derived class. To do this, we are 324 * Since we are using a system of base-classes, we want to call the 325 * destructor of the appropriate derived class. To do this, we are 327 326 * using virtual functions to implement the destructor. 328 327 */ … … 331 330 return 0; 332 331 } 333 332 334 333 return This->ref; 335 334 } … … 342 341 * See Windows documentation for more details on IStorage methods. 343 342 */ 344 HRESULT WINAPI StorageBaseImpl_OpenStream( 343 HRESULT WINAPI StorageBaseImpl_OpenStream( 345 344 IStorage* iface, 346 345 const OLECHAR* pwcsName, /* [string][in] */ 347 346 void* reserved1, /* [unique][in] */ 348 DWORD grfMode, /* [in] */ 349 DWORD reserved2, /* [in] */ 350 IStream** ppstm) /* [out] */ 347 DWORD grfMode, /* [in] */ 348 DWORD reserved2, /* [in] */ 349 IStream** ppstm) /* [out] */ 351 350 { 352 351 ICOM_THIS(StorageBaseImpl,iface); … … 357 356 HRESULT res = STG_E_UNKNOWN; 358 357 359 TRACE("(%p, %s, %p, %lx, %ld, %p)\n", 358 TRACE("(%p, %s, %p, %lx, %ld, %p)\n", 360 359 iface, debugstr_w(pwcsName), reserved1, grfMode, reserved2, ppstm); 361 360 … … 368 367 goto end; 369 368 } 370 369 371 370 /* 372 371 * Initialize the out parameter 373 372 */ 374 373 *ppstm = NULL; 375 374 376 375 /* 377 376 * Validate the STGM flags … … 398 397 */ 399 398 propertyEnumeration = IEnumSTATSTGImpl_Construct( 400 This->ancestorStorage, 399 This->ancestorStorage, 401 400 This->rootPropertySetIndex); 402 401 403 402 /* 404 403 * Search the enumeration for the property with the given name … … 408 407 pwcsName, 409 408 ¤tProperty); 410 409 411 410 /* 412 411 * Delete the property enumeration since we don't need it anymore 413 412 */ 414 413 IEnumSTATSTGImpl_Destroy(propertyEnumeration); 415 414 416 415 /* 417 416 * If it was found, construct the stream object and return a pointer to it. 418 417 */ 419 if ( (foundPropertyIndex!=PROPERTY_NULL) && 418 if ( (foundPropertyIndex!=PROPERTY_NULL) && 420 419 (currentProperty.propertyType==PROPTYPE_STREAM) ) 421 420 { 422 421 newStream = StgStreamImpl_Construct(This, grfMode, foundPropertyIndex); 423 422 424 423 if (newStream!=0) 425 424 { … … 428 427 429 428 /* 430 * Since we are returning a pointer to the interface, we have to 429 * Since we are returning a pointer to the interface, we have to 431 430 * nail down the reference. 432 431 */ 433 432 StgStreamImpl_AddRef(*ppstm); 434 433 435 434 res = S_OK; 436 435 goto end; 437 436 } 438 437 439 438 res = E_OUTOFMEMORY; 440 439 goto end; 441 440 } 442 441 443 442 res = STG_E_FILENOTFOUND; 444 443 … … 454 453 * 455 454 * This method will open a new storage object from the current storage. 456 * 455 * 457 456 * See Windows documentation for more details on IStorage methods. 458 */ 459 HRESULT WINAPI StorageBaseImpl_OpenStorage( 457 */ 458 HRESULT WINAPI StorageBaseImpl_OpenStorage( 460 459 IStorage* iface, 461 const OLECHAR* pwcsName, /* [string][unique][in] */ 462 IStorage* pstgPriority, /* [unique][in] */ 463 DWORD grfMode, /* [in] */ 464 SNB snbExclude, /* [unique][in] */ 465 DWORD reserved, /* [in] */ 466 IStorage** ppstg) /* [out] */ 460 const OLECHAR* pwcsName, /* [string][unique][in] */ 461 IStorage* pstgPriority, /* [unique][in] */ 462 DWORD grfMode, /* [in] */ 463 SNB snbExclude, /* [unique][in] */ 464 DWORD reserved, /* [in] */ 465 IStorage** ppstg) /* [out] */ 467 466 { 468 467 ICOM_THIS(StorageBaseImpl,iface); … … 473 472 HRESULT res = STG_E_UNKNOWN; 474 473 475 TRACE("(%p, %s, %p, %lx, %p, %ld, %p)\n", 476 iface, debugstr_w(pwcsName), pstgPriority, 474 TRACE("(%p, %s, %p, %lx, %p, %ld, %p)\n", 475 iface, debugstr_w(pwcsName), pstgPriority, 477 476 grfMode, snbExclude, reserved, ppstg); 478 477 479 478 /* 480 479 * Perform a sanity check on the parameters. … … 485 484 goto end; 486 485 } 487 486 488 487 /* as documented */ 489 488 if (snbExclude != NULL) … … 492 491 goto end; 493 492 } 494 493 495 494 /* 496 495 * Validate the STGM flags … … 505 504 * As documented. 506 505 */ 507 if ( !(grfMode & STGM_SHARE_EXCLUSIVE) || 506 if ( !(grfMode & STGM_SHARE_EXCLUSIVE) || 508 507 (grfMode & STGM_DELETEONRELEASE) || 509 508 (grfMode & STGM_PRIORITY) ) … … 517 516 */ 518 517 *ppstg = NULL; 519 518 520 519 /* 521 520 * Create a property enumeration to search the properties 522 521 */ 523 522 propertyEnumeration = IEnumSTATSTGImpl_Construct( 524 This->ancestorStorage, 523 This->ancestorStorage, 525 524 This->rootPropertySetIndex); 526 525 527 526 /* 528 527 * Search the enumeration for the property with the given name … … 532 531 pwcsName, 533 532 ¤tProperty); 534 533 535 534 /* 536 535 * Delete the property enumeration since we don't need it anymore 537 536 */ 538 537 IEnumSTATSTGImpl_Destroy(propertyEnumeration); 539 538 540 539 /* 541 540 * If it was found, construct the stream object and return a pointer to it. 542 541 */ 543 if ( (foundPropertyIndex!=PROPERTY_NULL) && 542 if ( (foundPropertyIndex!=PROPERTY_NULL) && 544 543 (currentProperty.propertyType==PROPTYPE_STORAGE) ) 545 544 { … … 550 549 This->ancestorStorage, 551 550 foundPropertyIndex); 552 551 553 552 if (newStorage != 0) 554 553 { … … 556 555 557 556 /* 558 * Since we are returning a pointer to the interface, 557 * Since we are returning a pointer to the interface, 559 558 * we have to nail down the reference. 560 559 */ 561 560 StorageBaseImpl_AddRef(*ppstg); 562 561 563 562 res = S_OK; 564 563 goto end; 565 564 } 566 565 567 566 res = STG_E_INSUFFICIENTMEMORY; 568 567 goto end; 569 568 } 570 569 571 570 res = STG_E_FILENOTFOUND; 572 571 … … 579 578 * Storage32BaseImpl_EnumElements (IStorage) 580 579 * 581 * This method will create an enumerator object that can be used to 580 * This method will create an enumerator object that can be used to 582 581 * retrieve informatino about all the properties in the storage object. 583 * 582 * 584 583 * See Windows documentation for more details on IStorage methods. 585 */ 586 HRESULT WINAPI StorageBaseImpl_EnumElements( 584 */ 585 HRESULT WINAPI StorageBaseImpl_EnumElements( 587 586 IStorage* iface, 588 DWORD reserved1, /* [in] */ 589 void* reserved2, /* [size_is][unique][in] */ 590 DWORD reserved3, /* [in] */ 591 IEnumSTATSTG** ppenum) /* [out] */ 587 DWORD reserved1, /* [in] */ 588 void* reserved2, /* [size_is][unique][in] */ 589 DWORD reserved3, /* [in] */ 590 IEnumSTATSTG** ppenum) /* [out] */ 592 591 { 593 592 ICOM_THIS(StorageBaseImpl,iface); 594 593 IEnumSTATSTGImpl* newEnum; 595 594 596 TRACE("(%p, %ld, %p, %ld, %p)\n", 595 TRACE("(%p, %ld, %p, %ld, %p)\n", 597 596 iface, reserved1, reserved2, reserved3, ppenum); 598 597 … … 602 601 if ( (This==0) || (ppenum==0)) 603 602 return E_INVALIDARG; 604 603 605 604 /* 606 605 * Construct the enumerator. … … 619 618 */ 620 619 IEnumSTATSTGImpl_AddRef(*ppenum); 621 620 622 621 return S_OK; 623 622 } … … 630 629 * 631 630 * This method will retrieve information about this storage object. 632 * 631 * 633 632 * See Windows documentation for more details on IStorage methods. 634 */ 635 HRESULT WINAPI StorageBaseImpl_Stat( 633 */ 634 HRESULT WINAPI StorageBaseImpl_Stat( 636 635 IStorage* iface, 637 STATSTG* pstatstg, /* [out] */ 638 DWORD grfStatFlag) /* [in] */ 636 STATSTG* pstatstg, /* [out] */ 637 DWORD grfStatFlag) /* [in] */ 639 638 { 640 639 ICOM_THIS(StorageBaseImpl,iface); … … 643 642 HRESULT res = STG_E_UNKNOWN; 644 643 645 TRACE("(%p, %p, %lx)\n", 644 TRACE("(%p, %p, %lx)\n", 646 645 iface, pstatstg, grfStatFlag); 647 646 … … 666 665 { 667 666 StorageUtl_CopyPropertyToSTATSTG( 668 pstatstg, 669 &curProperty, 667 pstatstg, 668 &curProperty, 670 669 grfStatFlag); 671 670 672 671 res = S_OK; 673 672 goto end; 674 673 } 675 674 676 675 res = E_FAIL; 677 676 … … 688 687 * Storage32BaseImpl_RenameElement (IStorage) 689 688 * 690 * This method will rename the specified element. 689 * This method will rename the specified element. 691 690 * 692 691 * See Windows documentation for more details on IStorage methods. 693 * 694 * Implementation notes: The method used to rename consists of creating a clone 695 * of the deleted StgProperty object setting it with the new name and to 692 * 693 * Implementation notes: The method used to rename consists of creating a clone 694 * of the deleted StgProperty object setting it with the new name and to 696 695 * perform a DestroyElement of the old StgProperty. 697 696 */ … … 706 705 ULONG foundPropertyIndex; 707 706 708 TRACE("(%p, %s, %s)\n", 707 TRACE("(%p, %s, %s)\n", 709 708 iface, debugstr_w(pwcsOldName), debugstr_w(pwcsNewName)); 710 709 … … 753 752 * Setup a new property for the renamed property 754 753 */ 755 renamedProperty.sizeOfNameString = 754 renamedProperty.sizeOfNameString = 756 755 ( lstrlenW(pwcsNewName)+1 ) * sizeof(WCHAR); 757 756 758 757 if (renamedProperty.sizeOfNameString > PROPERTY_NAME_BUFFER_LEN) 759 758 return STG_E_INVALIDNAME; 760 759 761 760 strcpyW(renamedProperty.name, pwcsNewName); 762 761 763 762 renamedProperty.propertyType = currentProperty.propertyType; 764 763 renamedProperty.startingBlock = currentProperty.startingBlock; 765 764 renamedProperty.size.s.LowPart = currentProperty.size.s.LowPart; 766 765 renamedProperty.size.s.HighPart = currentProperty.size.s.HighPart; 767 766 768 767 renamedProperty.previousProperty = PROPERTY_NULL; 769 768 renamedProperty.nextProperty = PROPERTY_NULL; 770 769 771 770 /* 772 771 * Bring the dirProperty link in case it is a storage and in which … … 774 773 */ 775 774 renamedProperty.dirProperty = currentProperty.dirProperty; 776 777 /* call CoFileTime to get the current time 775 776 /* call CoFileTime to get the current time 778 777 renamedProperty.timeStampS1 779 778 renamedProperty.timeStampD1 780 779 renamedProperty.timeStampS2 781 780 renamedProperty.timeStampD2 782 renamedProperty.propertyUniqueID 781 renamedProperty.propertyUniqueID 783 782 */ 784 785 /* 783 784 /* 786 785 * Obtain a free property in the property chain 787 786 */ 788 787 renamedPropertyIndex = getFreeProperty(This->ancestorStorage); 789 788 790 789 /* 791 790 * Save the new property into the new property spot 792 */ 791 */ 793 792 StorageImpl_WriteProperty( 794 793 This->ancestorStorage, 795 renamedPropertyIndex, 794 renamedPropertyIndex, 796 795 &renamedProperty); 797 798 /* 796 797 /* 799 798 * Find a spot in the property chain for our newly created property. 800 799 */ 801 800 updatePropertyChain( 802 801 (StorageImpl*)This, 803 renamedPropertyIndex, 802 renamedPropertyIndex, 804 803 renamedProperty); 805 804 806 805 /* 807 * At this point the renamed property has been inserted in the tree, 808 * now, before to Destroy the old property we must zeroed it's dirProperty 809 * otherwise the DestroyProperty below will zap it all and we do not want 806 * At this point the renamed property has been inserted in the tree, 807 * now, before to Destroy the old property we must zeroed it's dirProperty 808 * otherwise the DestroyProperty below will zap it all and we do not want 810 809 * this to happen. 811 810 * Also, we fake that the old property is a storage so the DestroyProperty 812 811 * will not do a SetSize(0) on the stream data. 813 * 812 * 814 813 * This means that we need to tweek the StgProperty if it is a stream or a 815 814 * non empty storage. … … 823 822 StorageImpl_WriteProperty( 824 823 This->ancestorStorage, 825 foundPropertyIndex, 824 foundPropertyIndex, 826 825 ¤tProperty); 827 826 828 /* 829 * Invoke Destroy to get rid of the ole property and automatically redo 830 * the linking of it's previous and next members... 831 */ 832 StorageImpl_DestroyElement((IStorage*)This->ancestorStorage, pwcsOldName); 827 /* 828 * Invoke Destroy to get rid of the ole property and automatically redo 829 * the linking of it's previous and next members... 830 */ 831 StorageImpl_DestroyElement((IStorage*)This->ancestorStorage, pwcsOldName); 833 832 834 833 } … … 847 846 * Storage32BaseImpl_CreateStream (IStorage) 848 847 * 849 * This method will create a stream object within this storage 848 * This method will create a stream object within this storage 850 849 * 851 850 * See Windows documentation for more details on IStorage methods. … … 865 864 ULONG foundPropertyIndex, newPropertyIndex; 866 865 867 TRACE("(%p, %s, %lx, %ld, %ld, %p)\n", 868 iface, debugstr_w(pwcsName), grfMode, 866 TRACE("(%p, %s, %lx, %ld, %ld, %p)\n", 867 iface, debugstr_w(pwcsName), grfMode, 869 868 reserved1, reserved2, ppstm); 870 869 … … 912 911 { 913 912 /* 914 * An element with this name already exists 913 * An element with this name already exists 915 914 */ 916 915 if (grfMode & STGM_CREATE) 917 916 { 918 IStorage_DestroyElement(iface, pwcsName); 919 } 920 else 917 IStorage_DestroyElement(iface, pwcsName); 918 } 919 else 921 920 return STG_E_FILEALREADYEXISTS; 922 921 } 923 922 924 /* 925 * memset the empty property 923 /* 924 * memset the empty property 926 925 */ 927 926 memset(&newStreamProperty, 0, sizeof(StgProperty)); … … 944 943 newStreamProperty.dirProperty = PROPERTY_NULL; 945 944 946 /* call CoFileTime to get the current time 945 /* call CoFileTime to get the current time 947 946 newStreamProperty.timeStampS1 948 947 newStreamProperty.timeStampD1 … … 954 953 955 954 /* 956 * Get a free property or create a new one 955 * Get a free property or create a new one 957 956 */ 958 957 newPropertyIndex = getFreeProperty(This->ancestorStorage); … … 960 959 /* 961 960 * Save the new property into the new property spot 962 */ 961 */ 963 962 StorageImpl_WriteProperty( 964 963 This->ancestorStorage, 965 newPropertyIndex, 964 newPropertyIndex, 966 965 &newStreamProperty); 967 966 968 /* 967 /* 969 968 * Find a spot in the property chain for our newly created property. 970 969 */ 971 970 updatePropertyChain( 972 971 (StorageImpl*)This, 973 newPropertyIndex, 972 newPropertyIndex, 974 973 newStreamProperty); 975 974 976 /* 975 /* 977 976 * Open the stream to return it. 978 977 */ … … 1000 999 * Storage32BaseImpl_SetClass (IStorage) 1001 1000 * 1002 * This method will write the specified CLSID in the property of this 1001 * This method will write the specified CLSID in the property of this 1003 1002 * storage. 1004 1003 * … … 1015 1014 1016 1015 TRACE("(%p, %p)\n", iface, clsid); 1017 1016 1018 1017 success = StorageImpl_ReadProperty(This->ancestorStorage, 1019 1018 This->rootPropertySetIndex, … … 1036 1035 ** Storage32Impl implementation 1037 1036 */ 1038 1037 1039 1038 /************************************************************************ 1040 1039 * Storage32Impl_CreateStorage (IStorage) … … 1044 1043 * See Windows documentation for more details on IStorage methods. 1045 1044 */ 1046 HRESULT WINAPI StorageImpl_CreateStorage( 1045 HRESULT WINAPI StorageImpl_CreateStorage( 1047 1046 IStorage* iface, 1048 const OLECHAR *pwcsName, /* [string][in] */ 1049 DWORD grfMode, /* [in] */ 1050 DWORD reserved1, /* [in] */ 1051 DWORD reserved2, /* [in] */ 1052 IStorage **ppstg) /* [out] */ 1047 const OLECHAR *pwcsName, /* [string][in] */ 1048 DWORD grfMode, /* [in] */ 1049 DWORD reserved1, /* [in] */ 1050 DWORD reserved2, /* [in] */ 1051 IStorage **ppstg) /* [out] */ 1053 1052 { 1054 1053 StorageImpl* const This=(StorageImpl*)iface; … … 1061 1060 HRESULT hr; 1062 1061 1063 TRACE("(%p, %s, %lx, %ld, %ld, %p)\n", 1064 iface, debugstr_w(pwcsName), grfMode, 1062 TRACE("(%p, %s, %lx, %ld, %ld, %p)\n", 1063 iface, debugstr_w(pwcsName), grfMode, 1065 1064 reserved1, reserved2, ppstg); 1066 1065 1067 1066 /* 1068 1067 * Validate parameters … … 1100 1099 { 1101 1100 /* 1102 * An element with this name already exists 1101 * An element with this name already exists 1103 1102 */ 1104 1103 if (grfMode & STGM_CREATE) 1105 IStorage_DestroyElement(iface, pwcsName); 1106 else 1104 IStorage_DestroyElement(iface, pwcsName); 1105 else 1107 1106 return STG_E_FILEALREADYEXISTS; 1108 1107 } 1109 1108 1110 /* 1111 * memset the empty property 1109 /* 1110 * memset the empty property 1112 1111 */ 1113 1112 memset(&newProperty, 0, sizeof(StgProperty)); … … 1129 1128 newProperty.dirProperty = PROPERTY_NULL; 1130 1129 1131 /* call CoFileTime to get the current time 1130 /* call CoFileTime to get the current time 1132 1131 newProperty.timeStampS1 1133 1132 newProperty.timeStampD1 … … 1138 1137 /* newStorageProperty.propertyUniqueID */ 1139 1138 1140 /* 1139 /* 1141 1140 * Obtain a free property in the property chain 1142 1141 */ … … 1145 1144 /* 1146 1145 * Save the new property into the new property spot 1147 */ 1146 */ 1148 1147 StorageImpl_WriteProperty( 1149 1148 This->ancestorStorage, 1150 newPropertyIndex, 1149 newPropertyIndex, 1151 1150 &newProperty); 1152 1151 1153 /* 1152 /* 1154 1153 * Find a spot in the property chain for our newly created property. 1155 1154 */ 1156 1155 updatePropertyChain( 1157 1156 This, 1158 newPropertyIndex, 1157 newPropertyIndex, 1159 1158 newProperty); 1160 1159 1161 /* 1160 /* 1162 1161 * Open it to get a pointer to return. 1163 1162 */ … … 1176 1175 } 1177 1176 1178 1177 1179 1178 return S_OK; 1180 1179 } … … 1207 1206 if (currentProperty.sizeOfNameString == 0) 1208 1207 { 1209 /* 1208 /* 1210 1209 * The property existis and is available, we found it. 1211 1210 */ … … 1224 1223 } while (newPropertyIndex == PROPERTY_NULL); 1225 1224 1226 /* 1227 * grow the property chain 1225 /* 1226 * grow the property chain 1228 1227 */ 1229 1228 if (! readSuccessful) … … 1235 1234 ULONG blockCount = 0; 1236 1235 1237 /* 1238 * obtain the new count of property blocks 1236 /* 1237 * obtain the new count of property blocks 1239 1238 */ 1240 1239 blockCount = BlockChainStream_GetCount( 1241 1240 storage->ancestorStorage->rootBlockChain)+1; 1242 1241 1243 /* 1244 * initialize the size used by the property stream 1242 /* 1243 * initialize the size used by the property stream 1245 1244 */ 1246 1245 newSize.s.HighPart = 0; 1247 1246 newSize.s.LowPart = storage->bigBlockSize * blockCount; 1248 1247 1249 /* 1250 * add a property block to the property chain 1248 /* 1249 * add a property block to the property chain 1251 1250 */ 1252 1251 BlockChainStream_SetSize(storage->ancestorStorage->rootBlockChain, newSize); 1253 1252 1254 /* 1255 * memset the empty property in order to initialize the unused newly 1253 /* 1254 * memset the empty property in order to initialize the unused newly 1256 1255 * created property 1257 1256 */ 1258 1257 memset(&emptyProperty, 0, sizeof(StgProperty)); 1259 1258 1260 /* 1259 /* 1261 1260 * initialize them 1262 1261 */ 1263 lastProperty = storage->bigBlockSize / PROPSET_BLOCK_SIZE * blockCount; 1264 1262 lastProperty = storage->bigBlockSize / PROPSET_BLOCK_SIZE * blockCount; 1263 1265 1264 for( 1266 1265 propertyIndex = newPropertyIndex; … … 1270 1269 StorageImpl_WriteProperty( 1271 1270 storage->ancestorStorage, 1272 propertyIndex, 1271 propertyIndex, 1273 1272 &emptyProperty); 1274 1273 } … … 1282 1281 * Internal Method 1283 1282 * 1284 * Case insensitive comparaison of StgProperty.name by first considering 1283 * Case insensitive comparaison of StgProperty.name by first considering 1285 1284 * their size. 1286 1285 * … … 1295 1294 LONG diff = lstrlenW(newProperty) - lstrlenW(currentProperty); 1296 1295 1297 if (diff == 0) 1298 { 1299 /* 1296 if (diff == 0) 1297 { 1298 /* 1300 1299 * We compare the string themselves only when they are of the same lenght 1301 1300 */ … … 1303 1302 } 1304 1303 1305 return diff; 1304 return diff; 1306 1305 } 1307 1306 … … 1315 1314 StorageImpl *storage, 1316 1315 ULONG newPropertyIndex, 1317 StgProperty newProperty) 1316 StgProperty newProperty) 1318 1317 { 1319 1318 StgProperty currentProperty; … … 1328 1327 if (currentProperty.dirProperty != PROPERTY_NULL) 1329 1328 { 1330 /* 1329 /* 1331 1330 * The root storage contains some element, therefore, start the research 1332 1331 * for the appropriate location. … … 1341 1340 1342 1341 /* 1343 * Read 1342 * Read 1344 1343 */ 1345 1344 StorageImpl_ReadProperty(storage->ancestorStorage, … … 1354 1353 { 1355 1354 LONG diff = propertyNameCmp( newProperty.name, currentProperty.name); 1356 1355 1357 1356 if (diff < 0) 1358 1357 { … … 1406 1405 else 1407 1406 { 1408 /* 1407 /* 1409 1408 * The root storage is empty, link the new property to it's dir property 1410 1409 */ … … 1416 1415 } 1417 1416 1418 1417 1419 1418 /************************************************************************* 1420 1419 * CopyTo (IStorage) 1421 1420 */ 1422 HRESULT WINAPI StorageImpl_CopyTo( 1421 HRESULT WINAPI StorageImpl_CopyTo( 1423 1422 IStorage* iface, 1424 DWORD ciidExclude, /* [in] */ 1425 const IID* rgiidExclude, /* [size_is][unique][in] */ 1426 SNB snbExclude, /* [unique][in] */ 1427 IStorage* pstgDest) /* [unique][in] */ 1423 DWORD ciidExclude, /* [in] */ 1424 const IID* rgiidExclude, /* [size_is][unique][in] */ 1425 SNB snbExclude, /* [unique][in] */ 1426 IStorage* pstgDest) /* [unique][in] */ 1428 1427 { 1429 1428 IEnumSTATSTG *elements = 0; … … 1436 1435 FIXME("Exclude option not implemented\n"); 1437 1436 1438 TRACE("(%p, %ld, %p, %p, %p)\n", 1439 iface, ciidExclude, rgiidExclude, 1437 TRACE("(%p, %ld, %p, %p, %p)\n", 1438 iface, ciidExclude, rgiidExclude, 1440 1439 snbExclude, pstgDest); 1441 1440 … … 1446 1445 return STG_E_INVALIDPOINTER; 1447 1446 1448 /* 1447 /* 1449 1448 * Enumerate the elements 1450 1449 */ … … 1459 1458 IStorage_Stat( iface, &curElement, STATFLAG_NONAME); 1460 1459 IStorage_SetClass( pstgDest, &curElement.clsid ); 1461 1460 1462 1461 do 1463 1462 { … … 1495 1494 return STG_E_ACCESSDENIED; 1496 1495 } 1497 1496 1498 1497 /* 1499 1498 * create a new storage in destination storage … … 1512 1511 NULL, 0, &pstgTmp ); 1513 1512 } 1514 1513 1515 1514 if (hr != S_OK) 1516 1515 break; 1517 1516 1518 1517 1519 1518 /* 1520 1519 * do the copy recursively … … 1522 1521 hr = IStorage_CopyTo( pstgChild, ciidExclude, rgiidExclude, 1523 1522 snbExclude, pstgTmp ); 1524 1523 1525 1524 IStorage_Release( pstgTmp ); 1526 1525 IStorage_Release( pstgChild ); … … 1558 1557 */ 1559 1558 IStream_SetSize(pstrTmp, strStat.cbSize); 1560 1559 1561 1560 /* 1562 1561 * do the copy … … 1564 1563 hr = IStream_CopyTo( pstrChild, pstrTmp, strStat.cbSize, 1565 1564 NULL, NULL ); 1566 1565 1567 1566 IStream_Release( pstrTmp ); 1568 1567 IStream_Release( pstrChild ); … … 1579 1578 */ 1580 1579 IEnumSTATSTG_Release(elements); 1581 1580 1582 1581 return hr; 1583 1582 } 1584 1583 1585 1584 /************************************************************************* 1586 1585 * MoveElementTo (IStorage) 1587 1586 */ 1588 HRESULT WINAPI StorageImpl_MoveElementTo( 1587 HRESULT WINAPI StorageImpl_MoveElementTo( 1589 1588 IStorage* iface, 1590 const OLECHAR *pwcsName, /* [string][in] */ 1591 IStorage *pstgDest, /* [unique][in] */ 1592 const OLECHAR *pwcsNewName,/* [string][in] */ 1593 DWORD grfFlags) /* [in] */ 1589 const OLECHAR *pwcsName, /* [string][in] */ 1590 IStorage *pstgDest, /* [unique][in] */ 1591 const OLECHAR *pwcsNewName,/* [string][in] */ 1592 DWORD grfFlags) /* [in] */ 1594 1593 { 1595 1594 FIXME("not implemented!\n"); 1596 1595 return E_NOTIMPL; 1597 1596 } 1598 1597 1599 1598 /************************************************************************* 1600 1599 * Commit (IStorage) 1601 1600 */ 1602 HRESULT WINAPI StorageImpl_Commit( 1601 HRESULT WINAPI StorageImpl_Commit( 1603 1602 IStorage* iface, 1604 DWORD grfCommitFlags)/* [in] */ 1603 DWORD grfCommitFlags)/* [in] */ 1605 1604 { 1606 1605 FIXME("(%ld): stub!\n", grfCommitFlags); 1607 1606 return S_OK; 1608 1607 } 1609 1608 1610 1609 /************************************************************************* 1611 1610 * Revert (IStorage) 1612 1611 */ 1613 HRESULT WINAPI StorageImpl_Revert( 1612 HRESULT WINAPI StorageImpl_Revert( 1614 1613 IStorage* iface) 1615 1614 { … … 1621 1620 * DestroyElement (IStorage) 1622 1621 * 1623 * Stategy: This implementation is build this way for simplicity not for speed. 1622 * Stategy: This implementation is build this way for simplicity not for speed. 1624 1623 * I always delete the top most element of the enumeration and adjust 1625 * the deleted element pointer all the time. This takes longer to 1626 * do but allow to reinvoke DestroyElement whenever we encounter a 1624 * the deleted element pointer all the time. This takes longer to 1625 * do but allow to reinvoke DestroyElement whenever we encounter a 1627 1626 * storage object. The optimisation reside in the usage of another 1628 * enumeration stategy that would give all the leaves of a storage 1627 * enumeration stategy that would give all the leaves of a storage 1629 1628 * first. (postfix order) 1630 1629 */ 1631 HRESULT WINAPI StorageImpl_DestroyElement( 1630 HRESULT WINAPI StorageImpl_DestroyElement( 1632 1631 IStorage* iface, 1633 const OLECHAR *pwcsName)/* [string][in] */ 1632 const OLECHAR *pwcsName)/* [string][in] */ 1634 1633 { 1635 1634 StorageImpl* const This=(StorageImpl*)iface; … … 1644 1643 ULONG parentPropertyId; 1645 1644 1646 TRACE("(%p, %s)\n", 1645 TRACE("(%p, %s)\n", 1647 1646 iface, debugstr_w(pwcsName)); 1648 1647 … … 1650 1649 * Perform a sanity check on the parameters. 1651 1650 */ 1652 if (pwcsName==NULL) 1651 if (pwcsName==NULL) 1653 1652 return STG_E_INVALIDPOINTER; 1654 1653 1655 1654 /* 1656 1655 * Create a property enumeration to search the property with the given name 1657 1656 */ 1658 1657 propertyEnumeration = IEnumSTATSTGImpl_Construct( 1659 This->ancestorStorage, 1658 This->ancestorStorage, 1660 1659 This->rootPropertySetIndex); 1661 1660 1662 1661 foundPropertyIndexToDelete = IEnumSTATSTGImpl_FindProperty( 1663 1662 propertyEnumeration, … … 1667 1666 IEnumSTATSTGImpl_Destroy(propertyEnumeration); 1668 1667 1669 if ( foundPropertyIndexToDelete == PROPERTY_NULL ) 1668 if ( foundPropertyIndexToDelete == PROPERTY_NULL ) 1670 1669 { 1671 1670 return STG_E_FILENOTFOUND; 1672 1671 } 1673 1672 1674 /* 1675 * Find the parent property of the property to delete (the one that 1676 * link to it). If This->dirProperty == foundPropertyIndexToDelete, 1673 /* 1674 * Find the parent property of the property to delete (the one that 1675 * link to it). If This->dirProperty == foundPropertyIndexToDelete, 1677 1676 * the parent is This. Otherwise, the parent is one of it's sibling... 1678 1677 */ 1679 1678 1680 /* 1679 /* 1681 1680 * First, read This's StgProperty.. 1682 1681 */ 1683 res = StorageImpl_ReadProperty( 1682 res = StorageImpl_ReadProperty( 1684 1683 This->ancestorStorage, 1685 1684 This->rootPropertySetIndex, … … 1688 1687 assert(res==TRUE); 1689 1688 1690 /* 1689 /* 1691 1690 * Second, check to see if by any chance the actual storage (This) is not 1692 1691 * the parent of the property to delete... We never know... … … 1694 1693 if ( parentProperty.dirProperty == foundPropertyIndexToDelete ) 1695 1694 { 1696 /* 1695 /* 1697 1696 * Set data as it would have been done in the else part... 1698 1697 */ … … 1700 1699 parentPropertyId = This->rootPropertySetIndex; 1701 1700 } 1702 else 1703 { 1704 /* 1705 * Create a property enumeration to search the parent properties, and 1701 else 1702 { 1703 /* 1704 * Create a property enumeration to search the parent properties, and 1706 1705 * delete it once done. 1707 1706 */ … … 1709 1708 1710 1709 propertyEnumeration2 = IEnumSTATSTGImpl_Construct( 1711 This->ancestorStorage, 1710 This->ancestorStorage, 1712 1711 This->rootPropertySetIndex); 1713 1712 1714 1713 typeOfRelation = IEnumSTATSTGImpl_FindParentProperty( 1715 1714 propertyEnumeration2, … … 1721 1720 } 1722 1721 1723 if ( propertyToDelete.propertyType == PROPTYPE_STORAGE ) 1722 if ( propertyToDelete.propertyType == PROPTYPE_STORAGE ) 1724 1723 { 1725 1724 hr = deleteStorageProperty( 1726 This, 1725 This, 1727 1726 foundPropertyIndexToDelete, 1728 1727 propertyToDelete); 1729 } 1728 } 1730 1729 else if ( propertyToDelete.propertyType == PROPTYPE_STREAM ) 1731 1730 { 1732 1731 hr = deleteStreamProperty( 1733 This, 1732 This, 1734 1733 foundPropertyIndexToDelete, 1735 1734 propertyToDelete); 1736 1735 } 1737 1736 1738 if (hr!=S_OK) 1737 if (hr!=S_OK) 1739 1738 return hr; 1740 1739 … … 1744 1743 hr = adjustPropertyChain( 1745 1744 This, 1746 propertyToDelete, 1745 propertyToDelete, 1747 1746 parentProperty, 1748 1747 parentPropertyId, … … 1753 1752 1754 1753 1755 /************************************************************************ 1756 * StorageImpl_Stat (IStorage) 1757 * 1758 * This method will retrieve information about this storage object. 1759 * 1760 * See Windows documentation for more details on IStorage methods. 1754 /************************************************************************ 1755 * StorageImpl_Stat (IStorage) 1756 * 1757 * This method will retrieve information about this storage object. 1758 * 1759 * See Windows documentation for more details on IStorage methods. 1761 1760 */ 1762 1761 HRESULT WINAPI StorageImpl_Stat( IStorage* iface, … … 1814 1813 } 1815 1814 1816 /* 1815 /* 1817 1816 * Enumerate the elements 1818 1817 */ … … 1828 1827 { 1829 1828 destroyHr = StorageImpl_DestroyElement( 1830 (IStorage*)childStorage, 1829 (IStorage*)childStorage, 1831 1830 (OLECHAR*)currentElement.pwcsName); 1832 1831 … … 1853 1852 IStorage_Release(childStorage); 1854 1853 IEnumSTATSTG_Release(elements); 1855 1854 1856 1855 return destroyHr; 1857 1856 } … … 1883 1882 0, 1884 1883 &pis); 1885 1884 1886 1885 if (hr!=S_OK) 1887 1886 { … … 1889 1888 } 1890 1889 1891 /* 1892 * Zap the stream 1893 */ 1894 hr = IStream_SetSize(pis, size); 1890 /* 1891 * Zap the stream 1892 */ 1893 hr = IStream_SetSize(pis, size); 1895 1894 1896 1895 if(hr != S_OK) … … 1904 1903 IStream_Release(pis); 1905 1904 1906 /* 1905 /* 1907 1906 * Invalidate the property by zeroing it's name member. 1908 1907 */ 1909 1908 propertyToDelete.sizeOfNameString = 0; 1910 1909 1911 /* 1910 /* 1912 1911 * Here we should re-read the property so we get the updated pointer 1913 1912 * but since we are here to zap it, I don't do it... 1914 1913 */ 1915 1914 StorageImpl_WriteProperty( 1916 parentStorage->ancestorStorage, 1915 parentStorage->ancestorStorage, 1917 1916 indexOfPropertyToDelete, 1918 1917 &propertyToDelete); … … 1943 1942 res = StorageImpl_ReadProperty( 1944 1943 storage->ancestorStorage, 1945 storePropertyIndex, 1944 storePropertyIndex, 1946 1945 &storeProperty); 1947 1946 … … 1957 1956 return findPlaceholder( 1958 1957 storage, 1959 propertyIndexToStore, 1958 propertyIndexToStore, 1960 1959 storeProperty.previousProperty, 1961 1960 typeOfRelation); … … 1972 1971 return findPlaceholder( 1973 1972 storage, 1974 propertyIndexToStore, 1973 propertyIndexToStore, 1975 1974 storeProperty.nextProperty, 1976 1975 typeOfRelation); … … 1980 1979 storeProperty.nextProperty = propertyIndexToStore; 1981 1980 } 1982 } 1981 } 1983 1982 else if (typeOfRelation == PROPERTY_RELATION_DIR) 1984 1983 { … … 1987 1986 return findPlaceholder( 1988 1987 storage, 1989 propertyIndexToStore, 1988 propertyIndexToStore, 1990 1989 storeProperty.dirProperty, 1991 1990 typeOfRelation); … … 1999 1998 hr = StorageImpl_WriteProperty( 2000 1999 storage->ancestorStorage, 2001 storePropertyIndex, 2000 storePropertyIndex, 2002 2001 &storeProperty); 2003 2002 … … 2014 2013 * Internal Method 2015 2014 * 2016 * This method takes the previous and the next property link of a property 2015 * This method takes the previous and the next property link of a property 2017 2016 * to be deleted and find them a place in the Storage. 2018 2017 */ 2019 static HRESULT adjustPropertyChain( 2018 static HRESULT adjustPropertyChain( 2020 2019 StorageImpl *This, 2021 2020 StgProperty propertyToDelete, … … 2031 2030 HRESULT hr = S_OK; 2032 2031 BOOL res = TRUE; 2033 2034 if (typeOfRelation == PROPERTY_RELATION_PREVIOUS) 2035 { 2036 if (propertyToDelete.previousProperty != PROPERTY_NULL) 2037 { 2038 /* 2032 2033 if (typeOfRelation == PROPERTY_RELATION_PREVIOUS) 2034 { 2035 if (propertyToDelete.previousProperty != PROPERTY_NULL) 2036 { 2037 /* 2039 2038 * Set the parent previous to the property to delete previous 2040 2039 */ 2041 2040 newLinkProperty = propertyToDelete.previousProperty; 2042 2041 2043 if (propertyToDelete.nextProperty != PROPERTY_NULL) 2042 if (propertyToDelete.nextProperty != PROPERTY_NULL) 2044 2043 { 2045 2044 /* 2046 * We also need to find a storage for the other link, setup variables 2045 * We also need to find a storage for the other link, setup variables 2047 2046 * to do this at the end... 2048 */ 2047 */ 2049 2048 needToFindAPlaceholder = TRUE; 2050 2049 storeNode = propertyToDelete.previousProperty; … … 2052 2051 relationType = PROPERTY_RELATION_NEXT; 2053 2052 } 2054 } 2055 else if (propertyToDelete.nextProperty != PROPERTY_NULL) 2056 { 2057 /* 2053 } 2054 else if (propertyToDelete.nextProperty != PROPERTY_NULL) 2055 { 2056 /* 2058 2057 * Set the parent previous to the property to delete next 2059 2058 */ 2060 2059 newLinkProperty = propertyToDelete.nextProperty; 2061 2060 } 2062 2063 /* 2061 2062 /* 2064 2063 * Link it for real... 2065 */ 2064 */ 2066 2065 parentProperty.previousProperty = newLinkProperty; 2067 2068 } 2069 else if (typeOfRelation == PROPERTY_RELATION_NEXT) 2070 { 2071 if (propertyToDelete.previousProperty != PROPERTY_NULL) 2072 { 2073 /* 2066 2067 } 2068 else if (typeOfRelation == PROPERTY_RELATION_NEXT) 2069 { 2070 if (propertyToDelete.previousProperty != PROPERTY_NULL) 2071 { 2072 /* 2074 2073 * Set the parent next to the property to delete next previous 2075 2074 */ 2076 2075 newLinkProperty = propertyToDelete.previousProperty; 2077 2078 if (propertyToDelete.nextProperty != PROPERTY_NULL) 2076 2077 if (propertyToDelete.nextProperty != PROPERTY_NULL) 2079 2078 { 2080 2079 /* 2081 * We also need to find a storage for the other link, setup variables 2080 * We also need to find a storage for the other link, setup variables 2082 2081 * to do this at the end... 2083 */ 2082 */ 2084 2083 needToFindAPlaceholder = TRUE; 2085 2084 storeNode = propertyToDelete.previousProperty; … … 2087 2086 relationType = PROPERTY_RELATION_NEXT; 2088 2087 } 2089 } 2090 else if (propertyToDelete.nextProperty != PROPERTY_NULL) 2091 { 2092 /* 2088 } 2089 else if (propertyToDelete.nextProperty != PROPERTY_NULL) 2090 { 2091 /* 2093 2092 * Set the parent next to the property to delete next 2094 2093 */ … … 2096 2095 } 2097 2096 2098 /* 2097 /* 2099 2098 * Link it for real... 2100 */ 2099 */ 2101 2100 parentProperty.nextProperty = newLinkProperty; 2102 } 2101 } 2103 2102 else /* (typeOfRelation == PROPERTY_RELATION_DIR) */ 2104 2103 { 2105 if (propertyToDelete.previousProperty != PROPERTY_NULL) 2106 { 2107 /* 2104 if (propertyToDelete.previousProperty != PROPERTY_NULL) 2105 { 2106 /* 2108 2107 * Set the parent dir to the property to delete previous 2109 2108 */ 2110 2109 newLinkProperty = propertyToDelete.previousProperty; 2111 2110 2112 if (propertyToDelete.nextProperty != PROPERTY_NULL) 2111 if (propertyToDelete.nextProperty != PROPERTY_NULL) 2113 2112 { 2114 2113 /* 2115 * We also need to find a storage for the other link, setup variables 2114 * We also need to find a storage for the other link, setup variables 2116 2115 * to do this at the end... 2117 */ 2116 */ 2118 2117 needToFindAPlaceholder = TRUE; 2119 2118 storeNode = propertyToDelete.previousProperty; … … 2121 2120 relationType = PROPERTY_RELATION_NEXT; 2122 2121 } 2123 } 2124 else if (propertyToDelete.nextProperty != PROPERTY_NULL) 2125 { 2126 /* 2122 } 2123 else if (propertyToDelete.nextProperty != PROPERTY_NULL) 2124 { 2125 /* 2127 2126 * Set the parent dir to the property to delete next 2128 2127 */ … … 2130 2129 } 2131 2130 2132 /* 2131 /* 2133 2132 * Link it for real... 2134 */ 2133 */ 2135 2134 parentProperty.dirProperty = newLinkProperty; 2136 2135 } 2137 2136 2138 /* 2139 * Write back the parent property 2137 /* 2138 * Write back the parent property 2140 2139 */ 2141 2140 res = StorageImpl_WriteProperty( 2142 This->ancestorStorage, 2141 This->ancestorStorage, 2143 2142 parentPropertyId, 2144 2143 &parentProperty); … … 2149 2148 2150 2149 /* 2151 * If a placeholder is required for the other link, then, find one and 2150 * If a placeholder is required for the other link, then, find one and 2152 2151 * get out of here... 2153 2152 */ 2154 if (needToFindAPlaceholder) 2153 if (needToFindAPlaceholder) 2155 2154 { 2156 2155 hr = findPlaceholder( 2157 This, 2158 toStoreNode, 2156 This, 2157 toStoreNode, 2159 2158 storeNode, 2160 2159 relationType); … … 2168 2167 * SetElementTimes (IStorage) 2169 2168 */ 2170 HRESULT WINAPI StorageImpl_SetElementTimes( 2169 HRESULT WINAPI StorageImpl_SetElementTimes( 2171 2170 IStorage* iface, 2172 const OLECHAR *pwcsName,/* [string][in] */ 2173 const FILETIME *pctime, /* [in] */ 2174 const FILETIME *patime, /* [in] */ 2175 const FILETIME *pmtime) /* [in] */ 2171 const OLECHAR *pwcsName,/* [string][in] */ 2172 const FILETIME *pctime, /* [in] */ 2173 const FILETIME *patime, /* [in] */ 2174 const FILETIME *pmtime) /* [in] */ 2176 2175 { 2177 2176 FIXME("(%s,...), stub!\n",debugstr_w(pwcsName)); … … 2182 2181 * SetStateBits (IStorage) 2183 2182 */ 2184 HRESULT WINAPI StorageImpl_SetStateBits( 2183 HRESULT WINAPI StorageImpl_SetStateBits( 2185 2184 IStorage* iface, 2186 DWORD grfStateBits,/* [in] */ 2187 DWORD grfMask) /* [in] */ 2185 DWORD grfStateBits,/* [in] */ 2186 DWORD grfMask) /* [in] */ 2188 2187 { 2189 2188 FIXME("not implemented!\n"); … … 2209 2208 2210 2209 memset(This, 0, sizeof(StorageImpl)); 2211 2210 2212 2211 /* 2213 2212 * Initialize the virtual function table. … … 2215 2214 ICOM_VTBL(This) = &Storage32Impl_Vtbl; 2216 2215 This->v_destructor = &StorageImpl_Destroy; 2217 2216 2218 2217 /* 2219 2218 * This is the top-level storage so initialize the ancestor pointer … … 2221 2220 */ 2222 2221 This->ancestorStorage = This; 2223 2222 2224 2223 /* 2225 2224 * Initialize the physical support of the storage. 2226 2225 */ 2227 2226 This->hFile = hFile; 2228 2227 2229 2228 /* 2230 2229 * Store copy of file path. 2231 2230 */ 2232 2231 if(pwcsName) { 2233 This->pwcsName = HeapAlloc(GetProcessHeap(), 0, 2232 This->pwcsName = HeapAlloc(GetProcessHeap(), 0, 2234 2233 (lstrlenW(pwcsName)+1)*sizeof(WCHAR)); 2235 2234 if (!This->pwcsName) 2236 2235 return STG_E_INSUFFICIENTMEMORY; 2237 strcpyW(This->pwcsName, pwcsName); 2236 strcpyW(This->pwcsName, pwcsName); 2238 2237 } 2239 2238 … … 2251 2250 if (This->bigBlockFile == 0) 2252 2251 return E_FAIL; 2253 2252 2254 2253 if (fileCreate) 2255 2254 { … … 2263 2262 * - There is no small block depot 2264 2263 */ 2265 memset( This->bigBlockDepotStart, 2266 BLOCK_UNUSED, 2264 memset( This->bigBlockDepotStart, 2265 BLOCK_UNUSED, 2267 2266 sizeof(This->bigBlockDepotStart)); 2268 2267 … … 2318 2317 */ 2319 2318 This->prevFreeBlock = 0; 2320 2319 2321 2320 /* 2322 2321 * Create the block chain abstractions. 2323 2322 */ 2324 This->rootBlockChain = 2323 This->rootBlockChain = 2325 2324 BlockChainStream_Construct(This, &This->rootStartBlock, PROPERTY_NULL); 2326 2325 2327 2326 This->smallBlockDepotChain = BlockChainStream_Construct( 2328 This, 2329 &This->smallBlockDepotStart, 2327 This, 2328 &This->smallBlockDepotStart, 2330 2329 PROPERTY_NULL); 2331 2330 2332 2331 /* 2333 * Write the root property 2332 * Write the root property 2334 2333 */ 2335 2334 if (fileCreate) … … 2358 2357 */ 2359 2358 currentPropertyIndex = 0; 2360 2359 2361 2360 do 2362 2361 { 2363 2362 readSuccessful = StorageImpl_ReadProperty( 2364 This, 2365 currentPropertyIndex, 2363 This, 2364 currentPropertyIndex, 2366 2365 ¤tProperty); 2367 2366 2368 2367 if (readSuccessful) 2369 2368 { … … 2376 2375 2377 2376 currentPropertyIndex++; 2378 2377 2379 2378 } while (readSuccessful && (This->rootPropertySetIndex == PROPERTY_NULL) ); 2380 2379 2381 2380 if (!readSuccessful) 2382 2381 { … … 2389 2388 */ 2390 2389 This->smallBlockRootChain = BlockChainStream_Construct( 2391 This, 2392 NULL, 2390 This, 2391 NULL, 2393 2392 This->rootPropertySetIndex); 2394 2393 2395 2394 return hr; 2396 2395 } … … 2928 2927 2929 2928 StorageUtl_ReadWord( 2930 headerBigBlock, 2931 OFFSET_BIGBLOCKSIZEBITS, 2929 headerBigBlock, 2930 OFFSET_BIGBLOCKSIZEBITS, 2932 2931 &This->bigBlockSizeBits); 2933 2932 2934 2933 StorageUtl_ReadWord( 2935 headerBigBlock, 2936 OFFSET_SMALLBLOCKSIZEBITS, 2934 headerBigBlock, 2935 OFFSET_SMALLBLOCKSIZEBITS, 2937 2936 &This->smallBlockSizeBits); 2938 2937 2939 2938 StorageUtl_ReadDWord( 2940 headerBigBlock, 2941 OFFSET_BBDEPOTCOUNT, 2939 headerBigBlock, 2940 OFFSET_BBDEPOTCOUNT, 2942 2941 &This->bigBlockDepotCount); 2943 2942 2944 2943 StorageUtl_ReadDWord( 2945 headerBigBlock, 2946 OFFSET_ROOTSTARTBLOCK, 2944 headerBigBlock, 2945 OFFSET_ROOTSTARTBLOCK, 2947 2946 &This->rootStartBlock); 2948 2947 2949 2948 StorageUtl_ReadDWord( 2950 headerBigBlock, 2951 OFFSET_SBDEPOTSTART, 2949 headerBigBlock, 2950 OFFSET_SBDEPOTSTART, 2952 2951 &This->smallBlockDepotStart); 2953 2952 2954 StorageUtl_ReadDWord( 2955 headerBigBlock, 2956 OFFSET_EXTBBDEPOTSTART, 2953 StorageUtl_ReadDWord( 2954 headerBigBlock, 2955 OFFSET_EXTBBDEPOTSTART, 2957 2956 &This->extBigBlockDepotStart); 2958 2957 2959 2958 StorageUtl_ReadDWord( 2960 headerBigBlock, 2961 OFFSET_EXTBBDEPOTCOUNT, 2959 headerBigBlock, 2960 OFFSET_EXTBBDEPOTCOUNT, 2962 2961 &This->extBigBlockDepotCount); 2963 2962 2964 2963 for (index = 0; index < COUNT_BBDEPOTINHEADER; index ++) 2965 2964 { 2966 2965 StorageUtl_ReadDWord( 2967 headerBigBlock, 2966 headerBigBlock, 2968 2967 OFFSET_BBDEPOTSTART + (sizeof(ULONG)*index), 2969 2968 &(This->bigBlockDepotStart[index])); 2970 2969 } 2971 2970 2972 2971 /* 2973 2972 * Make the bitwise arithmetic to get the size of the blocks in bytes. … … 2983 2982 This->smallBlockSize = 0x000000001 >> (DWORD)This->smallBlockSizeBits; 2984 2983 } 2985 2986 /* 2987 * Right now, the code is making some assumptions about the size of the 2984 2985 /* 2986 * Right now, the code is making some assumptions about the size of the 2988 2987 * blocks, just make sure they are what we're expecting. 2989 2988 */ … … 2996 2995 else 2997 2996 hr = S_OK; 2998 2997 2999 2998 /* 3000 2999 * Release the block. … … 3002 3001 StorageImpl_ReleaseBigBlock(This, headerBigBlock); 3003 3002 } 3004 3003 3005 3004 return hr; 3006 3005 } … … 3022 3021 */ 3023 3022 success = StorageImpl_ReadBigBlock(This, -1, headerBigBlock); 3024 3023 3025 3024 /* 3026 3025 * If the block read failed, the file is probably new. … … 3032 3031 */ 3033 3032 memset(headerBigBlock, 0, BIG_BLOCK_SIZE); 3034 3033 3035 3034 /* 3036 3035 * Initialize the magic number. 3037 3036 */ 3038 3037 memcpy(headerBigBlock, STORAGE_magic, sizeof(STORAGE_magic)); 3039 3038 3040 3039 /* 3041 3040 * And a bunch of things we don't know what they mean … … 3047 3046 StorageUtl_WriteDWord(headerBigBlock, 0x40, (DWORD)0x0001); 3048 3047 } 3049 3048 3050 3049 /* 3051 3050 * Write the information to the header. … … 3054 3053 { 3055 3054 StorageUtl_WriteWord( 3056 headerBigBlock, 3057 OFFSET_BIGBLOCKSIZEBITS, 3055 headerBigBlock, 3056 OFFSET_BIGBLOCKSIZEBITS, 3058 3057 This->bigBlockSizeBits); 3059 3058 3060 3059 StorageUtl_WriteWord( 3061 headerBigBlock, 3062 OFFSET_SMALLBLOCKSIZEBITS, 3060 headerBigBlock, 3061 OFFSET_SMALLBLOCKSIZEBITS, 3063 3062 This->smallBlockSizeBits); 3064 3063 3065 3064 StorageUtl_WriteDWord( 3066 headerBigBlock, 3067 OFFSET_BBDEPOTCOUNT, 3065 headerBigBlock, 3066 OFFSET_BBDEPOTCOUNT, 3068 3067 This->bigBlockDepotCount); 3069 3068 3070 3069 StorageUtl_WriteDWord( 3071 headerBigBlock, 3072 OFFSET_ROOTSTARTBLOCK, 3070 headerBigBlock, 3071 OFFSET_ROOTSTARTBLOCK, 3073 3072 This->rootStartBlock); 3074 3073 3075 3074 StorageUtl_WriteDWord( 3076 headerBigBlock, 3077 OFFSET_SBDEPOTSTART, 3075 headerBigBlock, 3076 OFFSET_SBDEPOTSTART, 3078 3077 This->smallBlockDepotStart); 3079 3078 3080 3079 StorageUtl_WriteDWord( 3081 headerBigBlock, 3082 OFFSET_EXTBBDEPOTSTART, 3080 headerBigBlock, 3081 OFFSET_EXTBBDEPOTSTART, 3083 3082 This->extBigBlockDepotStart); 3084 3083 3085 3084 StorageUtl_WriteDWord( 3086 headerBigBlock, 3087 OFFSET_EXTBBDEPOTCOUNT, 3085 headerBigBlock, 3086 OFFSET_EXTBBDEPOTCOUNT, 3088 3087 This->extBigBlockDepotCount); 3089 3088 … … 3091 3090 { 3092 3091 StorageUtl_WriteDWord( 3093 headerBigBlock, 3092 headerBigBlock, 3094 3093 OFFSET_BBDEPOTSTART + (sizeof(ULONG)*index), 3095 3094 (This->bigBlockDepotStart[index])); 3096 3095 } 3097 3096 } 3098 3097 3099 3098 /* 3100 3099 * Write the big block back to the file. … … 3120 3119 offsetInPropSet.s.HighPart = 0; 3121 3120 offsetInPropSet.s.LowPart = index * PROPSET_BLOCK_SIZE; 3122 3121 3123 3122 readSuccessful = BlockChainStream_ReadAt( 3124 3123 This->rootBlockChain, … … 3136 3135 memset(buffer->name, 0, sizeof(buffer->name)); 3137 3136 memcpy( 3138 buffer->name, 3139 propName, 3137 buffer->name, 3138 propName, 3140 3139 PROPERTY_NAME_BUFFER_LEN ); 3141 3140 TRACE("storage name: %s\n", debugstr_w(buffer->name)); 3142 3141 3143 3142 memcpy(&buffer->propertyType, currentProperty + OFFSET_PS_PROPERTYTYPE, 1); 3144 3143 3145 3144 StorageUtl_ReadWord( 3146 currentProperty, 3147 OFFSET_PS_NAMELENGTH, 3145 currentProperty, 3146 OFFSET_PS_NAMELENGTH, 3148 3147 &buffer->sizeOfNameString); 3149 3148 3150 3149 StorageUtl_ReadDWord( 3151 currentProperty, 3152 OFFSET_PS_PREVIOUSPROP, 3150 currentProperty, 3151 OFFSET_PS_PREVIOUSPROP, 3153 3152 &buffer->previousProperty); 3154 3153 3155 3154 StorageUtl_ReadDWord( 3156 currentProperty, 3157 OFFSET_PS_NEXTPROP, 3155 currentProperty, 3156 OFFSET_PS_NEXTPROP, 3158 3157 &buffer->nextProperty); 3159 3158 3160 3159 StorageUtl_ReadDWord( 3161 currentProperty, 3162 OFFSET_PS_DIRPROP, 3160 currentProperty, 3161 OFFSET_PS_DIRPROP, 3163 3162 &buffer->dirProperty); 3164 3163 3165 3164 StorageUtl_ReadGUID( 3166 currentProperty, 3167 OFFSET_PS_GUID, 3165 currentProperty, 3166 OFFSET_PS_GUID, 3168 3167 &buffer->propertyUniqueID); 3169 3168 3170 3169 StorageUtl_ReadDWord( 3171 currentProperty, 3172 OFFSET_PS_TSS1, 3170 currentProperty, 3171 OFFSET_PS_TSS1, 3173 3172 &buffer->timeStampS1); 3174 3173 3175 3174 StorageUtl_ReadDWord( 3176 currentProperty, 3177 OFFSET_PS_TSD1, 3175 currentProperty, 3176 OFFSET_PS_TSD1, 3178 3177 &buffer->timeStampD1); 3179 3178 3180 3179 StorageUtl_ReadDWord( 3181 currentProperty, 3182 OFFSET_PS_TSS2, 3180 currentProperty, 3181 OFFSET_PS_TSS2, 3183 3182 &buffer->timeStampS2); 3184 3183 3185 3184 StorageUtl_ReadDWord( 3186 currentProperty, 3187 OFFSET_PS_TSD2, 3185 currentProperty, 3186 OFFSET_PS_TSD2, 3188 3187 &buffer->timeStampD2); 3189 3188 3190 3189 StorageUtl_ReadDWord( 3191 currentProperty, 3192 OFFSET_PS_STARTBLOCK, 3190 currentProperty, 3191 OFFSET_PS_STARTBLOCK, 3193 3192 &buffer->startingBlock); 3194 3193 3195 3194 StorageUtl_ReadDWord( 3196 currentProperty, 3197 OFFSET_PS_SIZE, 3195 currentProperty, 3196 OFFSET_PS_SIZE, 3198 3197 &buffer->size.s.LowPart); 3199 3198 … … 3223 3222 3224 3223 memcpy( 3225 currentProperty + OFFSET_PS_NAME, 3226 buffer->name, 3224 currentProperty + OFFSET_PS_NAME, 3225 buffer->name, 3227 3226 PROPERTY_NAME_BUFFER_LEN ); 3228 3227 … … 3230 3229 3231 3230 StorageUtl_WriteWord( 3232 currentProperty, 3233 OFFSET_PS_NAMELENGTH, 3231 currentProperty, 3232 OFFSET_PS_NAMELENGTH, 3234 3233 buffer->sizeOfNameString); 3235 3234 3236 3235 StorageUtl_WriteDWord( 3237 currentProperty, 3238 OFFSET_PS_PREVIOUSPROP, 3236 currentProperty, 3237 OFFSET_PS_PREVIOUSPROP, 3239 3238 buffer->previousProperty); 3240 3239 3241 3240 StorageUtl_WriteDWord( 3242 currentProperty, 3243 OFFSET_PS_NEXTPROP, 3241 currentProperty, 3242 OFFSET_PS_NEXTPROP, 3244 3243 buffer->nextProperty); 3245 3244 3246 3245 StorageUtl_WriteDWord( 3247 currentProperty, 3248 OFFSET_PS_DIRPROP, 3246 currentProperty, 3247 OFFSET_PS_DIRPROP, 3249 3248 buffer->dirProperty); 3250 3249 3251 3250 StorageUtl_WriteGUID( 3252 currentProperty, 3253 OFFSET_PS_GUID, 3251 currentProperty, 3252 OFFSET_PS_GUID, 3254 3253 &buffer->propertyUniqueID); 3255 3254 3256 3255 StorageUtl_WriteDWord( 3257 currentProperty, 3258 OFFSET_PS_TSS1, 3256 currentProperty, 3257 OFFSET_PS_TSS1, 3259 3258 buffer->timeStampS1); 3260 3259 3261 3260 StorageUtl_WriteDWord( 3262 currentProperty, 3263 OFFSET_PS_TSD1, 3261 currentProperty, 3262 OFFSET_PS_TSD1, 3264 3263 buffer->timeStampD1); 3265 3264 3266 3265 StorageUtl_WriteDWord( 3267 currentProperty, 3268 OFFSET_PS_TSS2, 3266 currentProperty, 3267 OFFSET_PS_TSS2, 3269 3268 buffer->timeStampS2); 3270 3269 3271 3270 StorageUtl_WriteDWord( 3272 currentProperty, 3273 OFFSET_PS_TSD2, 3271 currentProperty, 3272 OFFSET_PS_TSD2, 3274 3273 buffer->timeStampD2); 3275 3274 3276 3275 StorageUtl_WriteDWord( 3277 currentProperty, 3278 OFFSET_PS_STARTBLOCK, 3276 currentProperty, 3277 OFFSET_PS_STARTBLOCK, 3279 3278 buffer->startingBlock); 3280 3279 3281 3280 StorageUtl_WriteDWord( 3282 currentProperty, 3283 OFFSET_PS_SIZE, 3281 currentProperty, 3282 OFFSET_PS_SIZE, 3284 3283 buffer->size.s.LowPart); 3285 3284 … … 3327 3326 3328 3327 StorageImpl_ReleaseBigBlock(This, bigBlockBuffer); 3329 3328 3330 3329 return TRUE; 3331 3330 } 3332 3331 3333 3332 return FALSE; 3334 3333 } … … 3460 3459 3461 3460 StorageInternalImpl* StorageInternalImpl_Construct( 3462 StorageImpl* ancestorStorage, 3461 StorageImpl* ancestorStorage, 3463 3462 ULONG rootPropertyIndex) 3464 3463 { … … 3511 3510 ** does nothing. 3512 3511 */ 3513 HRESULT WINAPI StorageInternalImpl_Commit( 3512 HRESULT WINAPI StorageInternalImpl_Commit( 3514 3513 IStorage* iface, 3515 DWORD grfCommitFlags) /* [in] */ 3514 DWORD grfCommitFlags) /* [in] */ 3516 3515 { 3517 3516 return S_OK; 3518 3517 } 3519 3518 3520 3519 /****************************************************************************** 3521 3520 ** … … 3525 3524 ** does nothing. 3526 3525 */ 3527 HRESULT WINAPI StorageInternalImpl_Revert( 3526 HRESULT WINAPI StorageInternalImpl_Revert( 3528 3527 IStorage* iface) 3529 3528 { … … 3542 3541 3543 3542 newEnumeration = HeapAlloc(GetProcessHeap(), 0, sizeof(IEnumSTATSTGImpl)); 3544 3543 3545 3544 if (newEnumeration!=0) 3546 3545 { … … 3550 3549 ICOM_VTBL(newEnumeration) = &IEnumSTATSTGImpl_Vtbl; 3551 3550 newEnumeration->ref = 0; 3552 3551 3553 3552 /* 3554 3553 * We want to nail-down the reference to the storage in case the … … 3557 3556 newEnumeration->parentStorage = parentStorage; 3558 3557 IStorage_AddRef((IStorage*)newEnumeration->parentStorage); 3559 3558 3560 3559 newEnumeration->firstPropertyNode = firstPropertyNode; 3561 3560 3562 3561 /* 3563 3562 * Initialize the search stack … … 3565 3564 newEnumeration->stackSize = 0; 3566 3565 newEnumeration->stackMaxSize = ENUMSTATSGT_SIZE_INCREMENT; 3567 newEnumeration->stackToVisit = 3566 newEnumeration->stackToVisit = 3568 3567 HeapAlloc(GetProcessHeap(), 0, sizeof(ULONG)*ENUMSTATSGT_SIZE_INCREMENT); 3569 3568 3570 3569 /* 3571 3570 * Make sure the current node of the iterator is the first one. … … 3573 3572 IEnumSTATSTGImpl_Reset((IEnumSTATSTG*)newEnumeration); 3574 3573 } 3575 3574 3576 3575 return newEnumeration; 3577 3576 } … … 3605 3604 * Compare the riid with the interface IDs implemented by this object. 3606 3605 */ 3607 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0) 3606 if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0) 3608 3607 { 3609 3608 *ppvObject = (IEnumSTATSTG*)This; 3610 3609 } 3611 else if (memcmp(&IID_IStorage, riid, sizeof(IID_IEnumSTATSTG)) == 0) 3610 else if (memcmp(&IID_IStorage, riid, sizeof(IID_IEnumSTATSTG)) == 0) 3612 3611 { 3613 3612 *ppvObject = (IEnumSTATSTG*)This; … … 3628 3627 return S_OK; 3629 3628 } 3630 3629 3631 3630 ULONG WINAPI IEnumSTATSTGImpl_AddRef( 3632 3631 IEnumSTATSTG* iface) … … 3637 3636 return This->ref; 3638 3637 } 3639 3638 3640 3639 ULONG WINAPI IEnumSTATSTGImpl_Release( 3641 3640 IEnumSTATSTG* iface) … … 3656 3655 } 3657 3656 3658 return newRef; ;3657 return newRef; 3659 3658 } 3660 3659 … … 3676 3675 */ 3677 3676 if ( (rgelt==0) || ( (celt!=1) && (pceltFetched==0) ) ) 3678 return E_INVALIDARG; 3679 3677 return E_INVALIDARG; 3678 3680 3679 /* 3681 3680 * To avoid the special case, get another pointer to a ULONG value if … … 3684 3683 if (pceltFetched==0) 3685 3684 pceltFetched = &objectFetched; 3686 3685 3687 3686 /* 3688 3687 * Start the iteration, we will iterate until we hit the end of the … … 3696 3695 currentSearchNode = IEnumSTATSTGImpl_PopSearchNode(This, FALSE); 3697 3696 3698 while ( ( *pceltFetched < celt) && 3697 while ( ( *pceltFetched < celt) && 3699 3698 ( currentSearchNode!=PROPERTY_NULL) ) 3700 3699 { 3701 /* 3700 /* 3702 3701 * Remove the top node from the stack 3703 3702 */ … … 3708 3707 */ 3709 3708 StorageImpl_ReadProperty(This->parentStorage, 3710 currentSearchNode, 3709 currentSearchNode, 3711 3710 ¤tProperty); 3712 3711 … … 3717 3716 ¤tProperty, 3718 3717 STATFLAG_DEFAULT); 3719 3718 3720 3719 /* 3721 3720 * Step to the next item in the iteration … … 3741 3740 } 3742 3741 3743 3742 3744 3743 HRESULT WINAPI IEnumSTATSTGImpl_Skip( 3745 3744 IEnumSTATSTG* iface, … … 3757 3756 currentSearchNode = IEnumSTATSTGImpl_PopSearchNode(This, FALSE); 3758 3757 3759 while ( (objectFetched < celt) && 3758 while ( (objectFetched < celt) && 3760 3759 (currentSearchNode!=PROPERTY_NULL) ) 3761 3760 { 3762 /* 3761 /* 3763 3762 * Remove the top node from the stack 3764 3763 */ … … 3769 3768 */ 3770 3769 StorageImpl_ReadProperty(This->parentStorage, 3771 currentSearchNode, 3770 currentSearchNode, 3772 3771 ¤tProperty); 3773 3772 3774 3773 /* 3775 3774 * Step to the next item in the iteration … … 3793 3792 return S_FALSE; 3794 3793 } 3795 3794 3796 3795 HRESULT WINAPI IEnumSTATSTGImpl_Reset( 3797 3796 IEnumSTATSTG* iface) … … 3812 3811 readSuccessful = StorageImpl_ReadProperty( 3813 3812 This->parentStorage, 3814 This->firstPropertyNode, 3813 This->firstPropertyNode, 3815 3814 &rootProperty); 3816 3815 … … 3827 3826 return S_OK; 3828 3827 } 3829 3828 3830 3829 HRESULT WINAPI IEnumSTATSTGImpl_Clone( 3831 3830 IEnumSTATSTG* iface, … … 3841 3840 if (ppenum==0) 3842 3841 return E_INVALIDARG; 3843 3842 3844 3843 newClone = IEnumSTATSTGImpl_Construct(This->parentStorage, 3845 3844 This->firstPropertyNode); 3846 3845 3847 3846 3848 3847 /* 3849 3848 * The new clone enumeration must point to the same current node as … … 3852 3851 newClone->stackSize = This->stackSize ; 3853 3852 newClone->stackMaxSize = This->stackMaxSize ; 3854 newClone->stackToVisit = 3853 newClone->stackToVisit = 3855 3854 HeapAlloc(GetProcessHeap(), 0, sizeof(ULONG) * newClone->stackMaxSize); 3856 3855 3857 3856 memcpy( 3858 newClone->stackToVisit, 3859 This->stackToVisit, 3857 newClone->stackToVisit, 3858 This->stackToVisit, 3860 3859 sizeof(ULONG) * newClone->stackSize); 3861 3860 … … 3873 3872 INT IEnumSTATSTGImpl_FindParentProperty( 3874 3873 IEnumSTATSTGImpl *This, 3875 ULONG childProperty, 3874 ULONG childProperty, 3876 3875 StgProperty *currentProperty, 3877 3876 ULONG *thisNodeId) … … 3891 3890 */ 3892 3891 currentSearchNode = IEnumSTATSTGImpl_PopSearchNode(This, FALSE); 3893 3892 3894 3893 3895 3894 while (currentSearchNode!=PROPERTY_NULL) … … 3900 3899 *thisNodeId = currentSearchNode; 3901 3900 3902 /* 3901 /* 3903 3902 * Remove the top node from the stack 3904 3903 */ … … 3910 3909 StorageImpl_ReadProperty( 3911 3910 This->parentStorage, 3912 currentSearchNode, 3911 currentSearchNode, 3913 3912 currentProperty); 3914 3913 3915 3914 if (currentProperty->previousProperty == childProperty) 3916 3915 return PROPERTY_RELATION_PREVIOUS; 3917 3916 3918 else if (currentProperty->nextProperty == childProperty) 3917 else if (currentProperty->nextProperty == childProperty) 3919 3918 return PROPERTY_RELATION_NEXT; 3920 3919 3921 3920 else if (currentProperty->dirProperty == childProperty) 3922 3921 return PROPERTY_RELATION_DIR; 3923 3922 3924 3923 /* 3925 3924 * Push the next search node in the search stack. … … 3950 3949 while (currentSearchNode!=PROPERTY_NULL) 3951 3950 { 3952 /* 3951 /* 3953 3952 * Remove the top node from the stack 3954 3953 */ … … 3959 3958 */ 3960 3959 StorageImpl_ReadProperty(This->parentStorage, 3961 currentSearchNode, 3960 currentSearchNode, 3962 3961 currentProperty); 3963 3962 3964 3963 if ( propertyNameCmp( 3965 (OLECHAR*)currentProperty->name, 3964 (OLECHAR*)currentProperty->name, 3966 3965 (OLECHAR*)lpszPropName) == 0) 3967 3966 return currentSearchNode; … … 4002 4001 4003 4002 This->stackToVisit = HeapReAlloc( 4004 GetProcessHeap(), 4003 GetProcessHeap(), 4005 4004 0, 4006 4005 This->stackToVisit, … … 4016 4015 readSuccessful = StorageImpl_ReadProperty( 4017 4016 This->parentStorage, 4018 nodeToPush, 4017 nodeToPush, 4019 4018 &rootProperty); 4020 4019 … … 4103 4102 else 4104 4103 { 4105 destination->pwcsName = 4104 destination->pwcsName = 4106 4105 CoTaskMemAlloc((lstrlenW(source->name)+1)*sizeof(WCHAR)); 4107 4106 4108 4107 strcpyW((LPWSTR)destination->pwcsName, source->name); 4109 4108 } 4110 4109 4111 4110 switch (source->propertyType) 4112 4111 { … … 4120 4119 default: 4121 4120 destination->type = STGTY_STREAM; 4122 break; 4121 break; 4123 4122 } 4124 4123 4125 4124 destination->cbSize = source->size; 4126 /* 4125 /* 4127 4126 currentReturnStruct->mtime = {0}; TODO 4128 4127 currentReturnStruct->ctime = {0}; 4129 currentReturnStruct->atime = {0}; 4128 currentReturnStruct->atime = {0}; 4130 4129 */ 4131 4130 destination->grfMode = 0; 4132 destination->grfLocksSupported = 0; 4131 destination->grfLocksSupported = 0; 4133 4132 destination->clsid = source->propertyUniqueID; 4134 destination->grfStateBits = 0; 4135 destination->reserved = 0; 4133 destination->grfStateBits = 0; 4134 destination->reserved = 0; 4136 4135 } 4137 4136 … … 4141 4140 4142 4141 BlockChainStream* BlockChainStream_Construct( 4143 StorageImpl* parentStorage, 4142 StorageImpl* parentStorage, 4144 4143 ULONG* headOfStreamPlaceHolder, 4145 4144 ULONG propertyIndex) … … 4214 4213 * Returns the number of blocks that comprises this chain. 4215 4214 * This is not the size of the stream as the last block may not be full! 4216 * 4215 * 4217 4216 */ 4218 4217 ULONG BlockChainStream_GetCount(BlockChainStream* This) … … 4228 4227 4229 4228 blockIndex = StorageImpl_GetNextBlockInChain( 4230 This->parentStorage, 4229 This->parentStorage, 4231 4230 blockIndex); 4232 4231 } … … 4236 4235 4237 4236 /****************************************************************************** 4238 * BlockChainStream_ReadAt 4237 * BlockChainStream_ReadAt 4239 4238 * 4240 4239 * Reads a specified number of bytes from this chain at the specified offset. … … 4276 4275 while ( (blockNoInSequence > 0) && (blockIndex != BLOCK_END_OF_CHAIN)) 4277 4276 { 4278 blockIndex = 4277 blockIndex = 4279 4278 StorageImpl_GetNextBlockInChain(This->parentStorage, blockIndex); 4280 4279 4281 4280 blockNoInSequence--; 4282 4281 } … … 4289 4288 *bytesRead = 0; 4290 4289 bufferWalker = buffer; 4291 4290 4292 4291 while ( (size > 0) && (blockIndex != BLOCK_END_OF_CHAIN) ) 4293 4292 { … … 4295 4294 * Calculate how many bytes we can copy from this big block. 4296 4295 */ 4297 bytesToReadInBuffer = 4296 bytesToReadInBuffer = 4298 4297 min(This->parentStorage->bigBlockSize - offsetInBlock, size); 4299 4298 4300 4299 /* 4301 4300 * Copy those bytes to the buffer 4302 4301 */ 4303 bigBlockBuffer = 4302 bigBlockBuffer = 4304 4303 StorageImpl_GetROBigBlock(This->parentStorage, blockIndex); 4305 4304 4306 4305 memcpy(bufferWalker, bigBlockBuffer + offsetInBlock, bytesToReadInBuffer); 4307 4306 4308 4307 StorageImpl_ReleaseBigBlock(This->parentStorage, bigBlockBuffer); 4309 4308 4310 4309 /* 4311 4310 * Step to the next big block. 4312 4311 */ 4313 blockIndex = 4312 blockIndex = 4314 4313 StorageImpl_GetNextBlockInChain(This->parentStorage, blockIndex); 4315 4314 … … 4320 4319 4321 4320 } 4322 4321 4323 4322 return (size == 0); 4324 4323 } … … 4365 4364 while ( (blockNoInSequence > 0) && (blockIndex != BLOCK_END_OF_CHAIN)) 4366 4365 { 4367 blockIndex = 4366 blockIndex = 4368 4367 StorageImpl_GetNextBlockInChain(This->parentStorage, blockIndex); 4369 4368 4370 4369 blockNoInSequence--; 4371 4370 } … … 4385 4384 * Calculate how many bytes we can copy from this big block. 4386 4385 */ 4387 bytesToWrite = 4386 bytesToWrite = 4388 4387 min(This->parentStorage->bigBlockSize - offsetInBlock, size); 4389 4388 4390 4389 /* 4391 4390 * Copy those bytes to the buffer 4392 4391 */ 4393 4392 bigBlockBuffer = StorageImpl_GetBigBlock(This->parentStorage, blockIndex); 4394 4393 4395 4394 memcpy(bigBlockBuffer + offsetInBlock, bufferWalker, bytesToWrite); 4396 4395 4397 4396 StorageImpl_ReleaseBigBlock(This->parentStorage, bigBlockBuffer); 4398 4397 4399 4398 /* 4400 4399 * Step to the next big block. 4401 4400 */ 4402 blockIndex = 4401 blockIndex = 4403 4402 StorageImpl_GetNextBlockInChain(This->parentStorage, blockIndex); 4404 4403 … … 4408 4407 offsetInBlock = 0; /* There is no offset on the next block */ 4409 4408 } 4410 4409 4411 4410 return (size == 0); 4412 4411 } … … 4445 4444 while (count < numBlocks) 4446 4445 { 4447 blockIndex = 4446 blockIndex = 4448 4447 StorageImpl_GetNextBlockInChain(This->parentStorage, blockIndex); 4449 4448 … … 4452 4451 4453 4452 /* Get the next block before marking the new end */ 4454 extraBlock = 4453 extraBlock = 4455 4454 StorageImpl_GetNextBlockInChain(This->parentStorage, blockIndex); 4456 4455 4457 4456 /* Mark the new end of chain */ 4458 4457 StorageImpl_SetNextBlockInChain( 4459 This->parentStorage, 4460 blockIndex, 4458 This->parentStorage, 4459 blockIndex, 4461 4460 BLOCK_END_OF_CHAIN); 4462 4461 … … 4469 4468 while (extraBlock != BLOCK_END_OF_CHAIN) 4470 4469 { 4471 blockIndex = 4470 blockIndex = 4472 4471 StorageImpl_GetNextBlockInChain(This->parentStorage, extraBlock); 4473 4472 … … 4513 4512 4514 4513 StorageImpl_ReadProperty( 4515 This->parentStorage, 4514 This->parentStorage, 4516 4515 This->ownerPropertyIndex, 4517 4516 &chainProp); 4518 4517 4519 chainProp.startingBlock = blockIndex; 4518 chainProp.startingBlock = blockIndex; 4520 4519 4521 4520 StorageImpl_WriteProperty( 4522 This->parentStorage, 4521 This->parentStorage, 4523 4522 This->ownerPropertyIndex, 4524 4523 &chainProp); … … 4569 4568 4570 4569 StorageImpl_SetNextBlockInChain( 4571 This->parentStorage, 4572 currentBlock, 4570 This->parentStorage, 4571 currentBlock, 4573 4572 blockIndex); 4574 4573 4575 4574 StorageImpl_SetNextBlockInChain( 4576 This->parentStorage, 4577 blockIndex, 4575 This->parentStorage, 4576 blockIndex, 4578 4577 BLOCK_END_OF_CHAIN); 4579 4578 … … 4597 4596 * TODO: Free the actual blocks in the file when we shrink the chain. 4598 4597 * Currently, the blocks are still in the file. So the file size 4599 * doesn't shrink even if we shrink streams. 4598 * doesn't shrink even if we shrink streams. 4600 4599 */ 4601 4600 BOOL BlockChainStream_SetSize( … … 4614 4613 else 4615 4614 { 4616 ULARGE_INTEGER fileSize = 4615 ULARGE_INTEGER fileSize = 4617 4616 BIGBLOCKFILE_GetSize(This->parentStorage->bigBlockFile); 4618 4617 … … 4623 4622 */ 4624 4623 if ((diff % This->parentStorage->bigBlockSize) != 0) 4625 diff += (This->parentStorage->bigBlockSize - 4624 diff += (This->parentStorage->bigBlockSize - 4626 4625 (diff % This->parentStorage->bigBlockSize) ); 4627 4626 … … 4647 4646 if(This->headOfStreamPlaceHolder == NULL) 4648 4647 { 4649 /* 4650 * This chain is a data stream read the property and return 4648 /* 4649 * This chain is a data stream read the property and return 4651 4650 * the appropriate size 4652 4651 */ … … 4661 4660 { 4662 4661 /* 4663 * this chain is a chain that does not have a property, figure out the 4664 * size by making the product number of used blocks times the 4662 * this chain is a chain that does not have a property, figure out the 4663 * size by making the product number of used blocks times the 4665 4664 * size of them 4666 4665 */ … … 4668 4667 result.s.HighPart = 0; 4669 4668 4670 result.s.LowPart = 4671 BlockChainStream_GetCount(This) * 4669 result.s.LowPart = 4670 BlockChainStream_GetCount(This) * 4672 4671 This->parentStorage->bigBlockSize; 4673 4672 … … 4681 4680 4682 4681 SmallBlockChainStream* SmallBlockChainStream_Construct( 4683 StorageImpl* parentStorage, 4682 StorageImpl* parentStorage, 4684 4683 ULONG propertyIndex) 4685 4684 { … … 4732 4731 * 4733 4732 * Returns the index of the next small block in this chain. 4734 * 4733 * 4735 4734 * Return Values: 4736 4735 * - BLOCK_END_OF_CHAIN: end of this chain … … 4859 4858 else 4860 4859 { 4861 ULONG count = 4860 ULONG count = 4862 4861 BlockChainStream_GetCount(This->parentStorage->smallBlockDepotChain); 4863 4862 … … 4870 4869 { 4871 4870 sbdIndex = nextBlock; 4872 nextBlock = 4871 nextBlock = 4873 4872 StorageImpl_GetNextBlockInChain(This->parentStorage, sbdIndex); 4874 4873 } … … 4877 4876 if (sbdIndex != BLOCK_END_OF_CHAIN) 4878 4877 StorageImpl_SetNextBlockInChain( 4879 This->parentStorage, 4880 sbdIndex, 4878 This->parentStorage, 4879 sbdIndex, 4881 4880 newsbdIndex); 4882 4881 4883 4882 StorageImpl_SetNextBlockInChain( 4884 This->parentStorage, 4885 newsbdIndex, 4883 This->parentStorage, 4884 newsbdIndex, 4886 4885 BLOCK_END_OF_CHAIN); 4887 4886 … … 4889 4888 * Initialize all the small blocks to free 4890 4889 */ 4891 smallBlockDepot = 4890 smallBlockDepot = 4892 4891 StorageImpl_GetBigBlock(This->parentStorage, newsbdIndex); 4893 4892 … … 4901 4900 */ 4902 4901 StgProperty rootProp; 4903 ULONG sbStartIndex; 4902 ULONG sbStartIndex; 4904 4903 4905 4904 /* … … 4910 4909 4911 4910 /* 4912 * And allocate the first big block that will contain small blocks 4911 * And allocate the first big block that will contain small blocks 4913 4912 */ 4914 sbStartIndex = 4913 sbStartIndex = 4915 4914 StorageImpl_GetNextFreeBigBlock(This->parentStorage); 4916 4915 4917 4916 StorageImpl_SetNextBlockInChain( 4918 This->parentStorage, 4919 sbStartIndex, 4917 This->parentStorage, 4918 sbStartIndex, 4920 4919 BLOCK_END_OF_CHAIN); 4921 4920 4922 4921 StorageImpl_ReadProperty( 4923 This->parentStorage, 4924 This->parentStorage->rootPropertySetIndex, 4922 This->parentStorage, 4923 This->parentStorage->rootPropertySetIndex, 4925 4924 &rootProp); 4926 4925 … … 4930 4929 4931 4930 StorageImpl_WriteProperty( 4932 This->parentStorage, 4933 This->parentStorage->rootPropertySetIndex, 4931 This->parentStorage, 4932 This->parentStorage->rootPropertySetIndex, 4934 4933 &rootProp); 4935 4934 } … … 4937 4936 } 4938 4937 4939 smallBlocksPerBigBlock = 4938 smallBlocksPerBigBlock = 4940 4939 This->parentStorage->bigBlockSize / This->parentStorage->smallBlockSize; 4941 4940 … … 4949 4948 4950 4949 StorageImpl_ReadProperty( 4951 This->parentStorage, 4952 This->parentStorage->rootPropertySetIndex, 4950 This->parentStorage, 4951 This->parentStorage->rootPropertySetIndex, 4953 4952 &rootProp); 4954 4953 4955 if (rootProp.size.s.LowPart < 4954 if (rootProp.size.s.LowPart < 4956 4955 (blocksRequired * This->parentStorage->bigBlockSize)) 4957 4956 { … … 4959 4958 4960 4959 BlockChainStream_SetSize( 4961 This->parentStorage->smallBlockRootChain, 4960 This->parentStorage->smallBlockRootChain, 4962 4961 rootProp.size); 4963 4962 4964 4963 StorageImpl_WriteProperty( 4965 This->parentStorage, 4966 This->parentStorage->rootPropertySetIndex, 4964 This->parentStorage, 4965 This->parentStorage->rootPropertySetIndex, 4967 4966 &rootProp); 4968 4967 } … … 4977 4976 * Reads a specified number of bytes from this chain at the specified offset. 4978 4977 * bytesRead may be NULL. 4979 * Failure will be returned if the specified number of bytes has not been read. 4978 * Failure will be returned if the specified number of bytes has not been read. 4980 4979 */ 4981 4980 BOOL SmallBlockChainStream_ReadAt( … … 4987 4986 { 4988 4987 ULARGE_INTEGER offsetInBigBlockFile; 4989 ULONG blockNoInSequence = 4988 ULONG blockNoInSequence = 4990 4989 offset.s.LowPart / This->parentStorage->smallBlockSize; 4991 4990 … … 5024 5023 * Calculate how many bytes we can copy from this small block. 5025 5024 */ 5026 bytesToReadInBuffer = 5025 bytesToReadInBuffer = 5027 5026 min(This->parentStorage->smallBlockSize - offsetInBlock, size); 5028 5027 … … 5031 5030 */ 5032 5031 offsetInBigBlockFile.s.HighPart = 0; 5033 offsetInBigBlockFile.s.LowPart = 5032 offsetInBigBlockFile.s.LowPart = 5034 5033 blockIndex * This->parentStorage->smallBlockSize; 5035 5034 … … 5075 5074 { 5076 5075 ULARGE_INTEGER offsetInBigBlockFile; 5077 ULONG blockNoInSequence = 5076 ULONG blockNoInSequence = 5078 5077 offset.s.LowPart / This->parentStorage->smallBlockSize; 5079 5078 … … 5083 5082 ULONG bytesWrittenFromBigBlockFile; 5084 5083 BYTE* bufferWalker; 5085 5084 5086 5085 /* 5087 5086 * This should never happen on a small block file. 5088 5087 */ 5089 5088 assert(offset.s.HighPart==0); 5090 5089 5091 5090 /* 5092 5091 * Find the first block in the stream that contains part of the buffer. 5093 5092 */ 5094 5093 blockIndex = SmallBlockChainStream_GetHeadOfChain(This); 5095 5094 5096 5095 while ( (blockNoInSequence > 0) && (blockIndex != BLOCK_END_OF_CHAIN)) 5097 5096 { 5098 5097 blockIndex = SmallBlockChainStream_GetNextBlockInChain(This, blockIndex); 5099 5098 5100 5099 blockNoInSequence--; 5101 5100 } 5102 5101 5103 5102 /* 5104 5103 * Start writing the buffer. … … 5114 5113 * Calculate how many bytes we can copy to this small block. 5115 5114 */ 5116 bytesToWriteInBuffer = 5115 bytesToWriteInBuffer = 5117 5116 min(This->parentStorage->smallBlockSize - offsetInBlock, size); 5118 5117 5119 5118 /* 5120 5119 * Calculate the offset of the small block in the small block file. 5121 5120 */ 5122 5121 offsetInBigBlockFile.s.HighPart = 0; 5123 offsetInBigBlockFile.s.LowPart = 5122 offsetInBigBlockFile.s.LowPart = 5124 5123 blockIndex * This->parentStorage->smallBlockSize; 5125 5124 5126 5125 offsetInBigBlockFile.s.LowPart += offsetInBlock; 5127 5126 5128 5127 /* 5129 5128 * Write those bytes in the buffer to the small block file. … … 5134 5133 bufferWalker, 5135 5134 &bytesWrittenFromBigBlockFile); 5136 5135 5137 5136 assert(bytesWrittenFromBigBlockFile == bytesToWriteInBuffer); 5138 5137 5139 5138 /* 5140 5139 * Step to the next big block. … … 5146 5145 offsetInBlock = 0; /* There is no offset on the next block */ 5147 5146 } 5148 5147 5149 5148 return (size == 0); 5150 5149 } … … 5153 5152 * SmallBlockChainStream_Shrink 5154 5153 * 5155 * Shrinks this chain in the small block depot. 5154 * Shrinks this chain in the small block depot. 5156 5155 */ 5157 5156 BOOL SmallBlockChainStream_Shrink( … … 5181 5180 /* 5182 5181 * If the count is 0, we have a special case, the head of the chain was 5183 * just freed. 5182 * just freed. 5184 5183 */ 5185 5184 if (count == 0) … … 5187 5186 StgProperty chainProp; 5188 5187 5189 StorageImpl_ReadProperty(This->parentStorage, 5188 StorageImpl_ReadProperty(This->parentStorage, 5190 5189 This->ownerPropertyIndex, 5191 5190 &chainProp); … … 5209 5208 /* Mark the new end of chain */ 5210 5209 SmallBlockChainStream_SetNextBlockInChain( 5211 This, 5212 blockIndex, 5210 This, 5211 blockIndex, 5213 5212 BLOCK_END_OF_CHAIN); 5214 5213 } … … 5224 5223 } 5225 5224 5226 return TRUE; 5225 return TRUE; 5227 5226 } 5228 5227 … … 5260 5259 blockIndex = chainProp.startingBlock; 5261 5260 SmallBlockChainStream_SetNextBlockInChain( 5262 This, 5263 blockIndex, 5261 This, 5262 blockIndex, 5264 5263 BLOCK_END_OF_CHAIN); 5265 5264 } … … 5294 5293 5295 5294 SmallBlockChainStream_SetNextBlockInChain( 5296 This, 5297 blockIndex, 5295 This, 5296 blockIndex, 5298 5297 BLOCK_END_OF_CHAIN); 5299 5298 … … 5336 5335 * TODO: Free the actual blocks in the file when we shrink the chain. 5337 5336 * Currently, the blocks are still in the file. So the file size 5338 * doesn't shrink even if we shrink streams. 5337 * doesn't shrink even if we shrink streams. 5339 5338 */ 5340 5339 BOOL SmallBlockChainStream_SetSize( … … 5394 5393 WCHAR tempFileName[MAX_PATH]; 5395 5394 5396 TRACE("(%s, %lx, %ld, %p)\n", 5397 debugstr_w(pwcsName), grfMode, 5395 TRACE("(%s, %lx, %ld, %p)\n", 5396 debugstr_w(pwcsName), grfMode, 5398 5397 reserved, ppstgOpen); 5399 5398 … … 5442 5441 5443 5442 /* 5444 * Interpret the STGM value grfMode 5443 * Interpret the STGM value grfMode 5445 5444 */ 5446 5445 shareMode = GetShareModeFromSTGM(grfMode); … … 5467 5466 fileAttributes, 5468 5467 0); 5469 5468 5470 5469 if (hFile == INVALID_HANDLE_VALUE) 5471 5470 { … … 5477 5476 */ 5478 5477 newStorage = HeapAlloc(GetProcessHeap(), 0, sizeof(StorageImpl)); 5479 5478 5480 5479 if (newStorage == 0) 5481 5480 return STG_E_INSUFFICIENTMEMORY; … … 5489 5488 TRUE, 5490 5489 TRUE); 5491 5490 5492 5491 if (FAILED(hr)) 5493 5492 { … … 5515 5514 DWORD grfMode, 5516 5515 SNB snbExclude, 5517 DWORD reserved, 5516 DWORD reserved, 5518 5517 IStorage **ppstgOpen) 5519 5518 { … … 5526 5525 DWORD length; 5527 5526 5528 TRACE("(%s, %p, %lx, %p, %ld, %p)\n", 5527 TRACE("(%s, %p, %lx, %p, %ld, %p)\n", 5529 5528 debugstr_w(pwcsName), pstgPriority, grfMode, 5530 5529 snbExclude, reserved, ppstgOpen); … … 5558 5557 */ 5559 5558 *ppstgOpen = 0; 5560 5561 hFile = CreateFileW( pwcsName, 5559 5560 hFile = CreateFileW( pwcsName, 5562 5561 accessMode, 5563 5562 shareMode, … … 5566 5565 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, 5567 5566 0); 5568 5567 5569 5568 length = GetFileSize(hFile, NULL); 5570 5569 5571 5570 if (hFile==INVALID_HANDLE_VALUE) 5572 5571 { … … 5605 5604 */ 5606 5605 newStorage = HeapAlloc(GetProcessHeap(), 0, sizeof(StorageImpl)); 5607 5606 5608 5607 if (newStorage == 0) 5609 5608 { … … 5621 5620 TRUE, 5622 5621 !length ); 5623 5622 5624 5623 if (FAILED(hr)) 5625 5624 { … … 5632 5631 goto end; 5633 5632 } 5634 5633 5635 5634 /* prepare the file name string given in lieu of the root property name */ 5636 5635 GetFullPathNameW(pwcsName, MAX_PATH, fullname, NULL); … … 5645 5644 (REFIID)&IID_IStorage, 5646 5645 (void**)ppstgOpen); 5647 5646 5648 5647 end: 5649 5648 TRACE("<-- %08lx, IStorage %p\n", hr, ppstgOpen ? *ppstgOpen : NULL); … … 5700 5699 (void**)ppstgOpen); 5701 5700 5702 return hr; 5701 return hr; 5703 5702 } 5704 5703 … … 5738 5737 */ 5739 5738 newStorage = HeapAlloc(GetProcessHeap(), 0, sizeof(StorageImpl)); 5740 5739 5741 5740 if (newStorage == 0) 5742 5741 return STG_E_INSUFFICIENTMEMORY; … … 5826 5825 STATSTG pstatstg; 5827 5826 HRESULT hRes; 5828 5827 5829 5828 TRACE("()\n"); 5830 5829 … … 5887 5886 CLSID clsid; 5888 5887 HRESULT res; 5889 5888 5890 5889 TRACE("(%p,%p)\n",pPStm,pStm); 5891 5890 … … 5893 5892 5894 5893 if (SUCCEEDED(res)){ 5895 5894 5896 5895 res=WriteClassStm(pStm,&clsid); 5897 5896 … … 5911 5910 * STGM_TRANSACTED 0x00010000 5912 5911 * STGM_SIMPLE 0x08000000 5913 * 5912 * 5914 5913 * STGM_READ 0x00000000 5915 5914 * STGM_WRITE 0x00000001 5916 5915 * STGM_READWRITE 0x00000002 5917 * 5916 * 5918 5917 * STGM_SHARE_DENY_NONE 0x00000040 5919 5918 * STGM_SHARE_DENY_READ 0x00000030 5920 5919 * STGM_SHARE_DENY_WRITE 0x00000020 5921 5920 * STGM_SHARE_EXCLUSIVE 0x00000010 5922 * 5921 * 5923 5922 * STGM_PRIORITY 0x00040000 5924 5923 * STGM_DELETEONRELEASE 0x04000000 … … 5936 5935 BOOL bSTGM_SIMPLE = ((stgm & STGM_SIMPLE) == STGM_SIMPLE); 5937 5936 BOOL bSTGM_DIRECT = ! (bSTGM_TRANSACTED || bSTGM_SIMPLE); 5938 5937 5939 5938 BOOL bSTGM_WRITE = ((stgm & STGM_WRITE) == STGM_WRITE); 5940 5939 BOOL bSTGM_READWRITE = ((stgm & STGM_READWRITE) == STGM_READWRITE); 5941 5940 BOOL bSTGM_READ = ! (bSTGM_WRITE || bSTGM_READWRITE); 5942 5941 5943 5942 BOOL bSTGM_SHARE_DENY_NONE = 5944 5943 ((stgm & STGM_SHARE_DENY_NONE) == STGM_SHARE_DENY_NONE); … … 5955 5954 BOOL bSTGM_CREATE = ((stgm & STGM_CREATE) == STGM_CREATE); 5956 5955 BOOL bSTGM_CONVERT = ((stgm & STGM_CONVERT) == STGM_CONVERT); 5957 5956 5958 5957 BOOL bSTGM_NOSCRATCH = ((stgm & STGM_NOSCRATCH) == STGM_NOSCRATCH); 5959 5958 BOOL bSTGM_NOSNAPSHOT = ((stgm & STGM_NOSNAPSHOT) == STGM_NOSNAPSHOT); 5960 5959 5961 /* 5960 /* 5962 5961 * STGM_DIRECT | STGM_TRANSACTED | STGM_SIMPLE 5963 5962 */ … … 5966 5965 return E_FAIL; 5967 5966 5968 /* 5967 /* 5969 5968 * STGM_WRITE | STGM_READWRITE | STGM_READ 5970 5969 */ … … 5974 5973 5975 5974 /* 5976 * STGM_SHARE_DENY_NONE | others 5975 * STGM_SHARE_DENY_NONE | others 5977 5976 * (I assume here that DENY_READ implies DENY_WRITE) 5978 5977 */ 5979 5978 if ( bSTGM_SHARE_DENY_NONE ) 5980 5979 if ( bSTGM_SHARE_DENY_READ || 5981 bSTGM_SHARE_DENY_WRITE || 5982 bSTGM_SHARE_EXCLUSIVE) 5980 bSTGM_SHARE_DENY_WRITE || 5981 bSTGM_SHARE_EXCLUSIVE) 5983 5982 return E_FAIL; 5984 5983 … … 5995 5994 if ( bSTGM_NOSCRATCH && ! bSTGM_TRANSACTED ) 5996 5995 return E_FAIL; 5997 5998 /* 5999 * STGM_NOSNAPSHOT requires STGM_TRANSACTED and 5996 5997 /* 5998 * STGM_NOSNAPSHOT requires STGM_TRANSACTED and 6000 5999 * not STGM_SHARE_EXCLUSIVE or STGM_SHARE_DENY_WRITE` 6001 6000 */ 6002 6001 if (bSTGM_NOSNAPSHOT) 6003 6002 { 6004 if ( ! ( bSTGM_TRANSACTED && 6003 if ( ! ( bSTGM_TRANSACTED && 6005 6004 !(bSTGM_SHARE_EXCLUSIVE || bSTGM_SHARE_DENY_WRITE)) ) 6006 6005 return E_FAIL; … … 6014 6013 * 6015 6014 * This method will return a share mode flag from a STGM value. 6016 * The STGM value is assumed valid. 6015 * The STGM value is assumed valid. 6017 6016 */ 6018 6017 static DWORD GetShareModeFromSTGM(DWORD stgm) … … 6090 6089 6091 6090 /************************************************************************* 6092 * OLECONVERT_LoadOLE10 [Internal] 6093 * 6094 * Loads the OLE10 STREAM to memory 6091 * OLECONVERT_LoadOLE10 [Internal] 6092 * 6093 * Loads the OLE10 STREAM to memory 6095 6094 * 6096 6095 * PARAMS … … 6105 6104 * NOTES 6106 6105 * This function is used by OleConvertOLESTREAMToIStorage only. 6107 * 6106 * 6108 6107 * Memory allocated for pData must be freed by the caller 6109 6108 */ … … 6260 6259 6261 6260 /************************************************************************* 6262 * OLECONVERT_SaveOLE10 [Internal] 6263 * 6264 * Saves the OLE10 STREAM From memory 6261 * OLECONVERT_SaveOLE10 [Internal] 6262 * 6263 * Saves the OLE10 STREAM From memory 6265 6264 * 6266 6265 * PARAMS … … 6274 6273 * NOTES 6275 6274 * This function is used by OleConvertIStorageToOLESTREAM only. 6276 * 6275 * 6277 6276 */ 6278 6277 HRESULT OLECONVERT_SaveOLE10(OLECONVERT_OLESTREAM_DATA *pData, LPOLESTREAM pOleStream) … … 6368 6367 6369 6368 /************************************************************************* 6370 * OLECONVERT_GetOLE20FromOLE10[Internal] 6369 * OLECONVERT_GetOLE20FromOLE10[Internal] 6371 6370 * 6372 6371 * This function copies OLE10 Data (the IStorage in the OLESTREAM) to disk, 6373 * opens it, and copies the content to the dest IStorage for 6372 * opens it, and copies the content to the dest IStorage for 6374 6373 * OleConvertOLESTREAMToIStorage 6375 * 6374 * 6376 6375 * 6377 6376 * PARAMS … … 6384 6383 * 6385 6384 * NOTES 6386 * 6387 * 6385 * 6386 * 6388 6387 */ 6389 6388 void OLECONVERT_GetOLE20FromOLE10(LPSTORAGE pDestStorage, BYTE *pBuffer, DWORD nBufferLength) … … 6420 6419 6421 6420 /************************************************************************* 6422 * OLECONVERT_WriteOLE20ToBuffer [Internal] 6423 * 6424 * Saves the OLE10 STREAM From memory 6421 * OLECONVERT_WriteOLE20ToBuffer [Internal] 6422 * 6423 * Saves the OLE10 STREAM From memory 6425 6424 * 6426 6425 * PARAMS … … 6435 6434 * 6436 6435 * Used by OleConvertIStorageToOLESTREAM only. 6437 * 6436 * 6438 6437 */ 6439 6438 DWORD OLECONVERT_WriteOLE20ToBuffer(LPSTORAGE pStorage, BYTE **pData) … … 6447 6446 6448 6447 *pData = NULL; 6449 6448 6450 6449 /* Create temp Storage */ 6451 6450 GetTempPathW(MAX_PATH, wstrTempDir); … … 6474 6473 6475 6474 /************************************************************************* 6476 * OLECONVERT_CreateOleStream [Internal] 6475 * OLECONVERT_CreateOleStream [Internal] 6477 6476 * 6478 6477 * Creates the "\001OLE" stream in the IStorage if neccessary. … … 6489 6488 * This stream is still unknown, MS Word seems to have extra data 6490 6489 * but since the data is stored in the OLESTREAM there should be 6491 * no need to recreate the stream. If the stream is manually 6490 * no need to recreate the stream. If the stream is manually 6492 6491 * deleted it will create it with this default data. 6493 * 6492 * 6494 6493 */ 6495 6494 void OLECONVERT_CreateOleStream(LPSTORAGE pStorage) … … 6498 6497 IStream *pStream; 6499 6498 WCHAR wstrStreamName[] = {1,'O', 'l', 'e', 0}; 6500 BYTE pOleStreamHeader [] = 6501 { 6502 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 6503 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 6504 0x00, 0x00, 0x00, 0x00 6499 BYTE pOleStreamHeader [] = 6500 { 6501 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 6502 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 6503 0x00, 0x00, 0x00, 0x00 6505 6504 }; 6506 6505 6507 6506 /* Create stream if not present */ 6508 hRes = IStorage_CreateStream(pStorage, wstrStreamName, 6507 hRes = IStorage_CreateStream(pStorage, wstrStreamName, 6509 6508 STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &pStream ); 6510 6509 … … 6519 6518 6520 6519 /************************************************************************* 6521 * OLECONVERT_CreateCompObjStream [Internal] 6520 * OLECONVERT_CreateCompObjStream [Internal] 6522 6521 * 6523 6522 * Creates a "\001CompObj" is the destination IStorage if necessary. 6524 6523 * 6525 6524 * PARAMS 6526 * pStorage [I] The dest IStorage to create the CompObj Stream 6525 * pStorage [I] The dest IStorage to create the CompObj Stream 6527 6526 * if necessary. 6528 6527 * strOleTypeName [I] The ProgID … … 6536 6535 * 6537 6536 * The stream data is stored in the OLESTREAM and there should be 6538 * no need to recreate the stream. If the stream is manually 6537 * no need to recreate the stream. If the stream is manually 6539 6538 * deleted it will attempt to create it by querying the registry. 6540 6539 * 6541 * 6540 * 6542 6541 */ 6543 6542 HRESULT OLECONVERT_CreateCompObjStream(LPSTORAGE pStorage, LPCSTR strOleTypeName) … … 6558 6557 6559 6558 /* Create a CompObj stream if it doesn't exist */ 6560 hStorageRes = IStorage_CreateStream(pStorage, wstrStreamName, 6559 hStorageRes = IStorage_CreateStream(pStorage, wstrStreamName, 6561 6560 STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &pStream ); 6562 6561 if(hStorageRes == S_OK) … … 6579 6578 LONG hErr; 6580 6579 /* Get the CLSID Default Name from the Registry */ 6581 hErr = RegOpenKeyA(HKEY_CLASSES_ROOT, IStorageCompObj.strProgIDName, &hKey); 6580 hErr = RegOpenKeyA(HKEY_CLASSES_ROOT, IStorageCompObj.strProgIDName, &hKey); 6582 6581 if(hErr == ERROR_SUCCESS) 6583 6582 { … … 6621 6620 6622 6621 /************************************************************************* 6623 * OLECONVERT_CreateOlePresStream[Internal] 6622 * OLECONVERT_CreateOlePresStream[Internal] 6624 6623 * 6625 6624 * Creates the "\002OlePres000" Stream with the Metafile data … … 6628 6627 * pStorage [I] The dest IStorage to create \002OLEPres000 stream in. 6629 6628 * dwExtentX [I] Width of the Metafile 6630 * dwExtentY [I] Height of the Metafile 6629 * dwExtentY [I] Height of the Metafile 6631 6630 * pData [I] Metafile data 6632 6631 * dwDataLength [I] Size of the Metafile data … … 6638 6637 * NOTES 6639 6638 * This function is used by OleConvertOLESTREAMToIStorage only. 6640 * 6639 * 6641 6640 */ 6642 6641 void OLECONVERT_CreateOlePresStream(LPSTORAGE pStorage, DWORD dwExtentX, DWORD dwExtentY , BYTE *pData, DWORD dwDataLength) … … 6645 6644 IStream *pStream; 6646 6645 WCHAR wstrStreamName[] = {2, 'O', 'l', 'e', 'P', 'r', 'e', 's', '0', '0', '0', 0}; 6647 BYTE pOlePresStreamHeader [] = 6648 { 6649 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 6650 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 6646 BYTE pOlePresStreamHeader [] = 6647 { 6648 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 6649 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 6651 6650 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 6652 6651 0x00, 0x00, 0x00, 0x00 6653 6652 }; 6654 6653 6655 BYTE pOlePresStreamHeaderEmpty [] = 6656 { 6657 0x00, 0x00, 0x00, 0x00, 6658 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 6654 BYTE pOlePresStreamHeaderEmpty [] = 6655 { 6656 0x00, 0x00, 0x00, 0x00, 6657 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 6659 6658 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 6660 6659 0x00, 0x00, 0x00, 0x00 6661 6660 }; 6662 6661 6663 6662 /* Create the OlePres000 Stream */ 6664 hRes = IStorage_CreateStream(pStorage, wstrStreamName, 6663 hRes = IStorage_CreateStream(pStorage, wstrStreamName, 6665 6664 STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &pStream ); 6666 6665 … … 6706 6705 6707 6706 /************************************************************************* 6708 * OLECONVERT_CreateOle10NativeStream [Internal] 6707 * OLECONVERT_CreateOle10NativeStream [Internal] 6709 6708 * 6710 6709 * Creates the "\001Ole10Native" Stream (should contain a BMP) … … 6722 6721 * 6723 6722 * Might need to verify the data and return appropriate error message 6724 * 6723 * 6725 6724 */ 6726 6725 void OLECONVERT_CreateOle10NativeStream(LPSTORAGE pStorage, BYTE *pData, DWORD dwDataLength) … … 6729 6728 IStream *pStream; 6730 6729 WCHAR wstrStreamName[] = {1, 'O', 'l', 'e', '1', '0', 'N', 'a', 't', 'i', 'v', 'e', 0}; 6731 6730 6732 6731 /* Create the Ole10Native Stream */ 6733 hRes = IStorage_CreateStream(pStorage, wstrStreamName, 6732 hRes = IStorage_CreateStream(pStorage, wstrStreamName, 6734 6733 STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &pStream ); 6735 6734 … … 6745 6744 6746 6745 /************************************************************************* 6747 * OLECONVERT_GetOLE10ProgID [Internal] 6746 * OLECONVERT_GetOLE10ProgID [Internal] 6748 6747 * 6749 6748 * Finds the ProgID (or OleTypeID) from the IStorage … … 6761 6760 * This function is used by OleConvertIStorageToOLESTREAM only. 6762 6761 * 6763 * 6762 * 6764 6763 */ 6765 6764 HRESULT OLECONVERT_GetOLE10ProgID(LPSTORAGE pStorage, char *strProgID, DWORD *dwSize) … … 6772 6771 6773 6772 /* Open the CompObj Stream */ 6774 hRes = IStorage_OpenStream(pStorage, wstrStreamName, NULL, 6773 hRes = IStorage_OpenStream(pStorage, wstrStreamName, NULL, 6775 6774 STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &pStream ); 6776 6775 if(hRes == S_OK) … … 6809 6808 *dwSize = WideCharToMultiByte(CP_ACP, 0, wstrProgID, -1, strProgID, *dwSize, NULL, FALSE); 6810 6809 } 6811 6810 6812 6811 } 6813 6812 return hRes; … … 6815 6814 6816 6815 /************************************************************************* 6817 * OLECONVERT_GetOle10PresData [Internal] 6816 * OLECONVERT_GetOle10PresData [Internal] 6818 6817 * 6819 6818 * Converts IStorage "/001Ole10Native" stream to a OLE10 Stream … … 6830 6829 * 6831 6830 * Memory allocated for pData must be freed by the caller 6832 * 6833 * 6831 * 6832 * 6834 6833 */ 6835 6834 void OLECONVERT_GetOle10PresData(LPSTORAGE pStorage, OLECONVERT_OLESTREAM_DATA *pOleStreamData) … … 6851 6850 6852 6851 /* Open Ole10Native Stream */ 6853 hRes = IStorage_OpenStream(pStorage, wstrStreamName, NULL, 6852 hRes = IStorage_OpenStream(pStorage, wstrStreamName, NULL, 6854 6853 STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &pStream ); 6855 6854 if(hRes == S_OK) … … 6870 6869 6871 6870 /************************************************************************* 6872 * OLECONVERT_GetOle20PresData[Internal] 6871 * OLECONVERT_GetOle20PresData[Internal] 6873 6872 * 6874 6873 * Converts IStorage "/002OlePres000" stream to a OLE10 Stream … … 6883 6882 * NOTES 6884 6883 * This function is used by OleConvertIStorageToOLESTREAM only. 6885 * 6884 * 6886 6885 * Memory allocated for pData must be freed by the caller 6887 6886 */ … … 6910 6909 6911 6910 /* Open OlePress000 stream */ 6912 hRes = IStorage_OpenStream(pStorage, wstrStreamName, NULL, 6911 hRes = IStorage_OpenStream(pStorage, wstrStreamName, NULL, 6913 6912 STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &pStream ); 6914 6913 if(hRes == S_OK) … … 6958 6957 6959 6958 /************************************************************************* 6960 * OleConvertOLESTREAMToIStorage [OLE32.87] 6959 * OleConvertOLESTREAMToIStorage [OLE32.87] 6961 6960 * 6962 6961 * Read info on MSDN … … 6967 6966 * Still some unknowns for the IStorage: "\002OlePres000", "\001CompObj", 6968 6967 * and "\001OLE" streams 6969 * 6968 * 6970 6969 */ 6971 6970 HRESULT WINAPI OleConvertOLESTREAMToIStorage ( 6972 LPOLESTREAM pOleStream, 6973 LPSTORAGE pstg, 6971 LPOLESTREAM pOleStream, 6972 LPSTORAGE pstg, 6974 6973 const DVTARGETDEVICE* ptd) 6975 6974 { … … 7062 7061 * Still some unknowns for the IStorage: "\002OlePres000", "\001CompObj", 7063 7062 * and "\001OLE" streams. 7064 * 7063 * 7065 7064 */ 7066 7065 HRESULT WINAPI OleConvertIStorageToOLESTREAM ( 7067 LPSTORAGE pstg, 7066 LPSTORAGE pstg, 7068 7067 LPOLESTREAM pOleStream) 7069 7068 { … … 7090 7089 { 7091 7090 /* Was it originally Ole10 */ 7092 hRes = IStorage_OpenStream(pstg, wstrStreamName, 0, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &pStream); 7091 hRes = IStorage_OpenStream(pstg, wstrStreamName, 0, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &pStream); 7093 7092 if(hRes == S_OK) 7094 7093 {
Note:
See TracChangeset
for help on using the changeset viewer.
