Sync up to trunk head.
[reactos.git] / dll / win32 / ole32 / storage32.c
index f1706da..434d8b2 100644 (file)
@@ -2583,6 +2583,7 @@ static HRESULT StorageImpl_Construct(
   DWORD        openFlags,
   BOOL         fileBased,
   BOOL         create,
+  ULONG        sector_size,
   StorageImpl** result)
 {
   StorageImpl* This;
@@ -2634,7 +2635,7 @@ static HRESULT StorageImpl_Construct(
   /*
    * Initialize the big block cache.
    */
-  This->bigBlockSize   = DEF_BIG_BLOCK_SIZE;
+  This->bigBlockSize   = sector_size;
   This->smallBlockSize = DEF_SMALL_BLOCK_SIZE;
   This->bigBlockFile   = BIGBLOCKFILE_Construct(hFile,
                                                 pLkbyt,
@@ -2665,8 +2666,12 @@ static HRESULT StorageImpl_Construct(
     This->bigBlockDepotCount    = 1;
     This->bigBlockDepotStart[0] = 0;
     This->rootStartBlock        = 1;
+    This->smallBlockLimit       = LIMIT_TO_USE_SMALL_BLOCK;
     This->smallBlockDepotStart  = BLOCK_END_OF_CHAIN;
-    This->bigBlockSizeBits      = DEF_BIG_BLOCK_SIZE_BITS;
+    if (sector_size == 4096)
+      This->bigBlockSizeBits      = MAX_BIG_BLOCK_SIZE_BITS;
+    else
+      This->bigBlockSizeBits      = MIN_BIG_BLOCK_SIZE_BITS;
     This->smallBlockSizeBits    = DEF_SMALL_BLOCK_SIZE_BITS;
     This->extBigBlockDepotStart = BLOCK_END_OF_CHAIN;
     This->extBigBlockDepotCount = 0;
@@ -2711,6 +2716,8 @@ static HRESULT StorageImpl_Construct(
    */
   This->prevFreeBlock = 0;
 
+  This->firstFreeSmallBlock = 0;
+
   /*
    * Create the block chain abstractions.
    */
@@ -3348,6 +3355,11 @@ static HRESULT StorageImpl_LoadFileHeader(
       OFFSET_ROOTSTARTBLOCK,
       &This->rootStartBlock);
 
+    StorageUtl_ReadDWord(
+      headerBigBlock,
+      OFFSET_SMALLBLOCKLIMIT,
+      &This->smallBlockLimit);
+
     StorageUtl_ReadDWord(
       headerBigBlock,
       OFFSET_SBDEPOTSTART,
@@ -3382,9 +3394,11 @@ static HRESULT StorageImpl_LoadFileHeader(
      * blocks, just make sure they are what we're expecting.
      */
     if ((This->bigBlockSize != MIN_BIG_BLOCK_SIZE && This->bigBlockSize != MAX_BIG_BLOCK_SIZE) ||
-       This->smallBlockSize != DEF_SMALL_BLOCK_SIZE)
+       This->smallBlockSize != DEF_SMALL_BLOCK_SIZE ||
+       This->smallBlockLimit != LIMIT_TO_USE_SMALL_BLOCK)
     {
-       WARN("Broken OLE storage file\n");
+       FIXME("Broken OLE storage file? bigblock=0x%x, smallblock=0x%x, sblimit=0x%x\n",
+           This->bigBlockSize, This->smallBlockSize, This->smallBlockLimit);
        hr = STG_E_INVALIDHEADER;
     }
     else
@@ -3438,7 +3452,6 @@ static void StorageImpl_SaveFileHeader(
     StorageUtl_WriteWord(headerBigBlock,  0x18, 0x3b);
     StorageUtl_WriteWord(headerBigBlock,  0x1a, 0x3);
     StorageUtl_WriteWord(headerBigBlock,  0x1c, (WORD)-2);
-    StorageUtl_WriteDWord(headerBigBlock, 0x38, (DWORD)0x1000);
   }
 
   /*
@@ -3464,6 +3477,11 @@ static void StorageImpl_SaveFileHeader(
     OFFSET_ROOTSTARTBLOCK,
     This->rootStartBlock);
 
+  StorageUtl_WriteDWord(
+    headerBigBlock,
+    OFFSET_SMALLBLOCKLIMIT,
+    This->smallBlockLimit);
+
   StorageUtl_WriteDWord(
     headerBigBlock,
     OFFSET_SBDEPOTSTART,
@@ -4341,13 +4359,14 @@ static HRESULT Storage_Construct(
   DWORD        openFlags,
   BOOL         fileBased,
   BOOL         create,
+  ULONG        sector_size,
   StorageBaseImpl** result)
 {
   StorageImpl *newStorage;
   StorageBaseImpl *newTransactedStorage;
   HRESULT hr;
 
-  hr = StorageImpl_Construct(hFile, pwcsName, pLkbyt, openFlags, fileBased, create, &newStorage);
+  hr = StorageImpl_Construct(hFile, pwcsName, pLkbyt, openFlags, fileBased, create, sector_size, &newStorage);
   if (FAILED(hr)) goto end;
 
   if (openFlags & STGM_TRANSACTED)
@@ -4840,6 +4859,7 @@ static StorageInternalImpl* StorageInternalImpl_Construct(
      * Initialize the virtual function table.
      */
     newStorage->base.lpVtbl = &Storage32InternalImpl_Vtbl;
+    newStorage->base.pssVtbl = &IPropertySetStorage_Vtbl;
     newStorage->base.baseVtbl = &StorageInternalImpl_BaseVtbl;
     newStorage->base.openFlags = (openFlags & ~STGM_CREATE);
 
@@ -5710,7 +5730,7 @@ static ULONG SmallBlockChainStream_GetNextFreeBlock(
   ULARGE_INTEGER offsetOfBlockInDepot;
   DWORD buffer;
   ULONG bytesRead;
-  ULONG blockIndex = 0;
+  ULONG blockIndex = This->parentStorage->firstFreeSmallBlock;
   ULONG nextBlockIndex = BLOCK_END_OF_CHAIN;
   HRESULT res = S_OK;
   ULONG smallBlocksPerBigBlock;
@@ -5819,6 +5839,8 @@ static ULONG SmallBlockChainStream_GetNextFreeBlock(
     }
   }
 
+  This->parentStorage->firstFreeSmallBlock = blockIndex+1;
+
   smallBlocksPerBigBlock =
     This->parentStorage->bigBlockSize / This->parentStorage->smallBlockSize;
 
@@ -6117,6 +6139,7 @@ static BOOL SmallBlockChainStream_Shrink(
                                                        &blockIndex)))
       return FALSE;
     SmallBlockChainStream_FreeBlock(This, extraBlock);
+    This->parentStorage->firstFreeSmallBlock = min(This->parentStorage->firstFreeSmallBlock, extraBlock);
     extraBlock = blockIndex;
   }
 
@@ -6293,30 +6316,13 @@ static ULARGE_INTEGER SmallBlockChainStream_GetSize(SmallBlockChainStream* This)
   return chainEntry.size;
 }
 
-/******************************************************************************
- *    StgCreateDocfile  [OLE32.@]
- * Creates a new compound file storage object
- *
- * PARAMS
- *  pwcsName  [ I] Unicode string with filename (can be relative or NULL)
- *  grfMode   [ I] Access mode for opening the new storage object (see STGM_ constants)
- *  reserved  [ ?] unused?, usually 0
- *  ppstgOpen [IO] A pointer to IStorage pointer to the new onject
- *
- * RETURNS
- *  S_OK if the file was successfully created
- *  some STG_E_ value if error
- * NOTES
- *  if pwcsName is NULL, create file with new unique name
- *  the function can returns
- *  STG_S_CONVERTED if the specified file was successfully converted to storage format
- *  (unrealized now)
- */
-HRESULT WINAPI StgCreateDocfile(
+static HRESULT create_storagefile(
   LPCOLESTR pwcsName,
   DWORD       grfMode,
-  DWORD       reserved,
-  IStorage  **ppstgOpen)
+  DWORD       grfAttrs,
+  STGOPTIONS* pStgOptions,
+  REFIID      riid,
+  void**      ppstgOpen)
 {
   StorageBaseImpl* newStorage = 0;
   HANDLE       hFile      = INVALID_HANDLE_VALUE;
@@ -6327,13 +6333,10 @@ HRESULT WINAPI StgCreateDocfile(
   DWORD          fileAttributes;
   WCHAR          tempFileName[MAX_PATH];
 
-  TRACE("(%s, %x, %d, %p)\n",
-       debugstr_w(pwcsName), grfMode,
-       reserved, ppstgOpen);
-
   if (ppstgOpen == 0)
     return STG_E_INVALIDPOINTER;
-  if (reserved != 0)
+
+  if (pStgOptions->ulSectorSize != MIN_BIG_BLOCK_SIZE && pStgOptions->ulSectorSize != MAX_BIG_BLOCK_SIZE)
     return STG_E_INVALIDPARAMETER;
 
   /* if no share mode given then DENY_NONE is the default */
@@ -6435,6 +6438,7 @@ HRESULT WINAPI StgCreateDocfile(
          grfMode,
          TRUE,
          TRUE,
+         pStgOptions->ulSectorSize,
          &newStorage);
 
   if (FAILED(hr))
@@ -6442,10 +6446,9 @@ HRESULT WINAPI StgCreateDocfile(
     goto end;
   }
 
-  /*
-   * Get an "out" pointer for the caller.
-   */
-  *ppstgOpen = (IStorage*)newStorage;
+  hr = IStorage_QueryInterface((IStorage*)newStorage, riid, ppstgOpen);
+
+  IStorage_Release((IStorage*)newStorage);
 
 end:
   TRACE("<-- %p  r = %08x\n", *ppstgOpen, hr);
@@ -6453,6 +6456,45 @@ end:
   return hr;
 }
 
+/******************************************************************************
+ *    StgCreateDocfile  [OLE32.@]
+ * Creates a new compound file storage object
+ *
+ * PARAMS
+ *  pwcsName  [ I] Unicode string with filename (can be relative or NULL)
+ *  grfMode   [ I] Access mode for opening the new storage object (see STGM_ constants)
+ *  reserved  [ ?] unused?, usually 0
+ *  ppstgOpen [IO] A pointer to IStorage pointer to the new onject
+ *
+ * RETURNS
+ *  S_OK if the file was successfully created
+ *  some STG_E_ value if error
+ * NOTES
+ *  if pwcsName is NULL, create file with new unique name
+ *  the function can returns
+ *  STG_S_CONVERTED if the specified file was successfully converted to storage format
+ *  (unrealized now)
+ */
+HRESULT WINAPI StgCreateDocfile(
+  LPCOLESTR pwcsName,
+  DWORD       grfMode,
+  DWORD       reserved,
+  IStorage  **ppstgOpen)
+{
+  STGOPTIONS stgoptions = {1, 0, 512};
+
+  TRACE("(%s, %x, %d, %p)\n",
+       debugstr_w(pwcsName), grfMode,
+       reserved, ppstgOpen);
+
+  if (ppstgOpen == 0)
+    return STG_E_INVALIDPOINTER;
+  if (reserved != 0)
+    return STG_E_INVALIDPARAMETER;
+
+  return create_storagefile(pwcsName, grfMode, 0, &stgoptions, &IID_IStorage, (void**)ppstgOpen);
+}
+
 /******************************************************************************
  *              StgCreateStorageEx        [OLE32.@]
  */
@@ -6481,10 +6523,10 @@ HRESULT WINAPI StgCreateStorageEx(const WCHAR* pwcsName, DWORD grfMode, DWORD st
 
     if (stgfmt == STGFMT_STORAGE || stgfmt == STGFMT_DOCFILE)
     {
-        FIXME("Stub: calling StgCreateDocfile, but ignoring pStgOptions and grfAttrs\n");
-        return StgCreateDocfile(pwcsName, grfMode, 0, (IStorage **)ppObjectOpen); 
+        return create_storagefile(pwcsName, grfMode, grfAttrs, pStgOptions, riid, ppObjectOpen);
     }
 
+
     ERR("Invalid stgfmt argument\n");
     return STG_E_INVALIDPARAMETER;
 }
@@ -6707,6 +6749,7 @@ HRESULT WINAPI StgOpenStorage(
          grfMode,
          TRUE,
          FALSE,
+         512,
          &newStorage);
 
   if (FAILED(hr))
@@ -6754,6 +6797,7 @@ HRESULT WINAPI StgCreateDocfileOnILockBytes(
          grfMode,
          FALSE,
          TRUE,
+         512,
          &newStorage);
 
   if (FAILED(hr))
@@ -6801,6 +6845,7 @@ HRESULT WINAPI StgOpenStorageOnILockBytes(
          grfMode,
          FALSE,
          FALSE,
+         512,
          &newStorage);
 
   if (FAILED(hr))