2 * reactos Cache Manager (Cc*) pin Bcb handling of libcaptive
3 * Copyright (C) 2003 Jan Kratochvil <project-captive@jankratochvil.net>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; exactly version 2 of June 1991 is required
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "privatebcbpin.h"
23 #include "reactos/ddk/ccfuncs.h"
24 #include "privatebcb.h"
25 #include "captive/macros.h"
30 * @FileObject: Initialized open #FileObject to map.
31 * %NULL value is forbidden.
32 * @MappedFileOffset: The @FileObject file offset from where to map the region from.
33 * Negative value is forbidden.
34 * @MappedLength: Requested length of the region to map from @FileObject.
35 * FIXME: Value %0 is currently forbidden by libcaptive; it should be allowed.
36 * @Wait: Whether disk waiting is permitted for this function.
37 * Value currently ignored by libcaptive as the data must have been mapped by CcMapData() already anyway.
38 * @Flags: %PIN_WAIT means whether disk waiting is permitted for this function.
39 * Value without %PIN_WAIT is currently permtted by libcaptive as the data must have been mapped by CcMapData() already anyway.
40 * %PIN_NO_READ is the same as %MAP_NO_READ - see CcMapData().
41 * FIXME: %PIN_EXCLUSIVE for exclusive @Bcb access is now ignored by libcaptive.
42 * %PIN_IF_BCB if @Bcb should never be created; function is successful only if @Bcb already exists.
43 * @Bcb: Returns initialized #PUBLIC_BCB to refer to the mapped region.
44 * The memory region can be larger than requested as it is %PAGE_SIZE aligned.
45 * %NULL pointer is forbidden.
46 * @Buffer: Returns the mapped memory region start address.
47 * This address may not be %PAGE_SIZE aligned.
48 * %NULL pointer is forbidden.
50 * This function will allow you to modify the data mapped by CcMapData().
51 * libcaptive does not differentiate this function with CcMapData().
53 * This call does not set the buffer as dirty - such buffer will not be flushed automatically.
55 * NEVER re-read any memory from FileObject here!
56 * at least fastfat.sys directory create relies on the fact of CcPinRead()
57 * with already modified buffers to be left intact.
59 * This call will proceed as CcPinRead() if such #Bcb does not yet exist.
60 * This is IMO just a bug workaround for a peruse by fastfat.sys FatLocateVolumeLabel().
62 * Every call to this function must be matched by a one corresponding CcUnpinData() call.
64 * Returns: %TRUE if the region was successfuly mapped.
65 * @Bcb with the initialized new memory region.
66 * @Buffer with the address of the exact byte specified by @FileOffset.
68 BOOLEAN CcPinMappedData
69 (IN PFILE_OBJECT FileObject,IN PLARGE_INTEGER FileOffset,IN ULONG Length,IN ULONG Flags,OUT PVOID *Bcb)
71 CaptiveSharedCacheMapObject *SharedCacheMap;
72 CaptivePrivateBcbPinObject *captive_private_bcb_pin_object;
75 g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"enter: CcPinMappedData: FileObject=0x%lX,FileOffset=0x%lX,Length=0x%lX,Flags=0x%lX",
76 (long)FileObject,(!FileOffset ? -1 : (long)FileOffset->QuadPart),Length,Flags);
78 g_return_val_if_fail(FileObject!=NULL,FALSE);
79 g_return_val_if_fail(FileOffset!=NULL,FALSE);
80 g_return_val_if_fail(FileOffset->QuadPart>=0,FALSE);
81 g_return_val_if_fail(Length>0,FALSE); /* FIXME: not handled below; 0 should be allowed */
82 g_return_val_if_fail(Flags==PIN_WAIT,FALSE); /* FIXME */
83 g_return_val_if_fail(Bcb!=NULL,FALSE);
85 g_assert(Length<=PAGE_SIZE);
86 /* Check PAGE_SIZE crossing */
87 g_assert((FileOffset->QuadPart&~(PAGE_SIZE-1))==((FileOffset->QuadPart+Length-1)&~(PAGE_SIZE-1)));
89 SharedCacheMap=captive_FileObject_to_SharedCacheMap(FileObject);
90 /* Do not invalide 'map'ped data otherwise ntfs.sys of NT-5.1sp1 mount crashes.
92 captive_private_bcb_pin_object=captive_private_bcb_pin_object_get_ref(SharedCacheMap,
93 CAPTIVE_ROUND_DOWN64(FileOffset->QuadPart,PAGE_SIZE),
94 FALSE); /* invalidate_new */
96 captive_shared_cache_map_data_validate_noread(SharedCacheMap,FileOffset->QuadPart,FileOffset->QuadPart+Length);
98 *Bcb=captive_private_bcb_object_get_PublicBcb(CAPTIVE_PRIVATE_BCB_OBJECT(captive_private_bcb_pin_object));
101 g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"leave: CcPinMappedData: r=%d,Bcb=0x%lX",
102 r,(!Bcb ? -1 : (long)*Bcb));
110 * @FileObject: Initialized open #FileObject to map.
111 * %NULL value is forbidden.
112 * @FileOffset: The @FileObject file offset from where to map the region from.
113 * Negative value is forbidden.
114 * @Length: Requested length of the region to map from @FileObject.
115 * FIXME: Value %0 is currently forbidden by libcaptive; it should be allowed.
116 * @Flags: %PIN_WAIT means whether disk waiting is permitted for this function.
117 * Value without %PIN_WAIT is currently permtted by libcaptive as the data must have been mapped by CcMapData() already anyway.
118 * %PIN_NO_READ is the same as %MAP_NO_READ - see CcMapData().
119 * FIXME: %PIN_EXCLUSIVE for exclusive @Bcb access is now ignored by libcaptive.
120 * %PIN_IF_BCB if @Bcb should never be created; function is successful only if @Bcb already exists.
121 * @Bcb: Returns initialized #PUBLIC_BCB to refer to the mapped region.
122 * The memory region can be larger than requested as it is %PAGE_SIZE aligned.
123 * %NULL pointer is forbidden.
124 * @Buffer: Returns the mapped memory region start address.
125 * This address may not be %PAGE_SIZE aligned.
126 * %NULL pointer is forbidden.
128 * Merely a shortcut call for CcMapData() and CcPinMappedData() afterwards.
129 * See these two functions for the details. It has a difference to subsequent
130 * calling of CcMapData() and CcPinMappedData() instead as this call counts
131 * only as one function for a corresponding CcUnpinData() call.
133 * This call does not set the buffer as dirty - such buffer will not be flushed automatically.
135 * Every call to this function must be matched by a one corresponding CcUnpinData() call.
137 * Returns: %TRUE if the region was successfuly mapped.
138 * @Bcb with the initialized new memory region.
139 * @Buffer with the address of the exact byte specified by @FileOffset.
141 BOOLEAN CcPinRead(IN PFILE_OBJECT FileObject,
142 IN PLARGE_INTEGER FileOffset,IN ULONG Length,IN ULONG Flags,OUT PVOID *Bcb,OUT PVOID *Buffer)
144 CaptiveSharedCacheMapObject *SharedCacheMap;
145 CaptivePrivateBcbPinObject *captive_private_bcb_pin_object;
148 g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"enter: CcPinRead: FileObject=0x%lX,FileOffset=0x%lX,Length=0x%lX,Flags=0x%lX",
149 (long)FileObject,(!FileOffset ? -1 : (long)FileOffset->QuadPart),Length,Flags);
151 g_return_val_if_fail(FileObject!=NULL,FALSE);
152 g_return_val_if_fail(FileOffset!=NULL,FALSE);
153 g_return_val_if_fail(FileOffset->QuadPart>=0,FALSE);
154 g_return_val_if_fail(Length>0,FALSE); /* FIXME: not handled below; 0 should be allowed */
155 g_return_val_if_fail((Flags&~PIN_IF_BCB)==PIN_WAIT,FALSE); /* FIXME */
156 g_return_val_if_fail(Bcb!=NULL,FALSE);
157 g_return_val_if_fail(Buffer!=NULL,FALSE);
159 g_assert(Length<=PAGE_SIZE);
160 /* Check PAGE_SIZE crossing */
161 g_assert((FileOffset->QuadPart&~(PAGE_SIZE-1))==((FileOffset->QuadPart+Length-1)&~(PAGE_SIZE-1)));
163 SharedCacheMap=captive_FileObject_to_SharedCacheMap(FileObject);
165 if (Flags&PIN_IF_BCB) {
166 if ((captive_private_bcb_pin_object=captive_private_bcb_pin_object_get(SharedCacheMap,
167 CAPTIVE_ROUND_DOWN64(FileOffset->QuadPart,PAGE_SIZE))))
168 g_object_ref(captive_private_bcb_pin_object);
171 /* Invalide possibly only 'map'ped data as we need to re-read them on CcPinRead().
172 * Otherwise any file written by fastfat.sys of NT-5.1sp1 will corrupt
173 * the code+55AA of DOS boot sector (disk offset 0x0).
175 captive_private_bcb_pin_object=captive_private_bcb_pin_object_get_ref(SharedCacheMap,
176 CAPTIVE_ROUND_DOWN64(FileOffset->QuadPart,PAGE_SIZE),
177 TRUE); /* invalidate_new */
180 if (captive_private_bcb_pin_object) {
181 captive_shared_cache_map_data_validate_read(SharedCacheMap,FileObject,FileOffset->QuadPart,FileOffset->QuadPart+Length);
183 *Bcb=captive_private_bcb_object_get_PublicBcb(CAPTIVE_PRIVATE_BCB_OBJECT(captive_private_bcb_pin_object));
185 *Buffer=captive_shared_cache_map_get_buffer(SharedCacheMap)+FileOffset->QuadPart;
186 r=!!captive_private_bcb_pin_object;
188 g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"leave: CcPinRead: r=%d,Bcb=0x%lX,Buffer=0x%lX",
189 r,(!Bcb ? -1 : (long)*Bcb),(!Buffer ? -1 : (long)*Buffer));
196 * CcSetDirtyPinnedData:
197 * @Bcb: #PUBLIB_BCB to be unpinned from CcRepinBcb().
198 * %NULL value is forbidden.
199 * @Lsn: Optional LSN (Linear Sequence Number) to assign to @Bcb.
200 * %NULL pointer is permitted.
202 * This call will set the buffer as dirty - such buffer will be flushed automatically.
204 * You should call it only on CcPin*() buffers - not just CcMapData() buffers
205 * although libcaptive does not differentiate it.
207 VOID CcSetDirtyPinnedData(IN PVOID Bcb,IN PLARGE_INTEGER Lsn OPTIONAL)
209 CaptivePrivateBcbPinObject *captive_private_bcb_pin_object;
211 g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"enter: CcSetDirtyPinnedData: BcbVoid=0x%lX,Lsn=0x%lX",
212 (long)Bcb,(!Lsn ? -1 : (long)Lsn->QuadPart));
214 g_return_if_fail(Bcb!=NULL);
216 captive_private_bcb_pin_object=CAPTIVE_PRIVATE_BCB_PIN_OBJECT(captive_PublicBcb_to_PrivateBcbObject(Bcb));
218 captive_private_bcb_pin_object_set_dirty(captive_private_bcb_pin_object);
220 captive_private_bcb_pin_object_set_lsn(captive_private_bcb_pin_object,Lsn->QuadPart);
222 g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"leave: CcSetDirtyPinnedData");
228 * @FileObject: Initialized open #FileObject to map.
229 * %NULL value is forbidden.
230 * @FileOffset: The @FileObject file offset from where to map the region from.
231 * Negative value is forbidden.
232 * @Length: Requested length of the region to map from @FileObject.
233 * FIXME: Value %0 is currently forbidden by libcaptive; it should be allowed.
234 * @Zero: %TRUE if the area of @FileOffset...@FileOffset+@Length should be cleared.
235 * @Flags: %PIN_WAIT means whether disk waiting is permitted for this function.
236 * Value without %PIN_WAIT is currently permtted by libcaptive as the data must have been mapped by CcMapData() already anyway.
237 * %PIN_NO_READ is the same as %MAP_NO_READ - see CcMapData().
238 * FIXME: %PIN_EXCLUSIVE for exclusive @Bcb access is now ignored by libcaptive.
239 * %PIN_IF_BCB if @Bcb should never be created; function is successful only if @Bcb already exists.
240 * @Bcb: Returns initialized #PUBLIC_BCB to refer to the mapped region.
241 * The memory region can be larger than requested as it is %PAGE_SIZE aligned.
242 * %NULL pointer is forbidden.
243 * @Buffer: Returns the mapped memory region start address.
244 * This address may not be %PAGE_SIZE aligned.
245 * %NULL pointer is forbidden.
247 * Wrapper for a pair of CcPinRead() and CcSetDirtyPinnedData().
248 * The mapped range can be also optionally cleared if @Zero is specified.
249 * See CcPinRead() for a more detailed documentation.
251 * This call will set the buffer as dirty - such buffer will be flushed automatically.
253 * Returns: %TRUE if the mapping was successful.
255 BOOLEAN CcPreparePinWrite(IN PFILE_OBJECT FileObject,
256 IN PLARGE_INTEGER FileOffset,IN ULONG Length,IN BOOLEAN Zero,IN ULONG Flags,OUT PVOID *Bcb,OUT PVOID *Buffer)
258 CaptiveSharedCacheMapObject *SharedCacheMap;
259 CaptivePrivateBcbPinObject *captive_private_bcb_pin_object;
262 g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"enter: CcPreparePinWrite: FileObject=0x%lX,FileOffset=0x%lX,Length=0x%lX,Zero=%d,Flags=0x%lX",
263 (long)FileObject,(!FileOffset ? -1 : (long)FileOffset->QuadPart),Length,Zero,Flags);
265 g_return_val_if_fail(FileObject!=NULL,FALSE);
266 g_return_val_if_fail(FileOffset!=NULL,FALSE);
267 g_return_val_if_fail(FileOffset->QuadPart>=0,FALSE);
268 g_return_val_if_fail(Length>0,FALSE); /* FIXME: not handled below; 0 should be allowed */
269 g_return_val_if_fail(Flags==PIN_WAIT,FALSE); /* FIXME */
270 g_return_val_if_fail(Bcb!=NULL,FALSE);
271 g_return_val_if_fail(Buffer!=NULL,FALSE);
273 g_assert(0==CAPTIVE_ROUND_DOWN_EXCEEDING64(FileOffset->QuadPart,PAGE_SIZE)); /* NOT YET IMPLEMENTED */
274 g_assert(Length==PAGE_SIZE); /* NOT YET IMPLEMENTED */
276 SharedCacheMap=captive_FileObject_to_SharedCacheMap(FileObject);
277 captive_private_bcb_pin_object=captive_private_bcb_pin_object_get_ref(SharedCacheMap,
278 CAPTIVE_ROUND_DOWN64(FileOffset->QuadPart,PAGE_SIZE),
279 FALSE); /* invalidate_new: FIXME: Is it compatible? */
281 captive_shared_cache_map_set_data_valid(SharedCacheMap,FileOffset->QuadPart,FileOffset->QuadPart+Length);
283 memset(captive_shared_cache_map_get_buffer(SharedCacheMap)+FileOffset->QuadPart,0,Length);
284 captive_shared_cache_map_set_dirty(SharedCacheMap,FileOffset->QuadPart,FileOffset->QuadPart+Length);
286 *Bcb=captive_private_bcb_object_get_PublicBcb(CAPTIVE_PRIVATE_BCB_OBJECT(captive_private_bcb_pin_object));
287 *Buffer=captive_shared_cache_map_get_buffer(SharedCacheMap)+FileOffset->QuadPart;
290 g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"leave: CcPreparePinWrite: r=%d,Bcb=0x%lX,Buffer=0x%lX",
291 r,(!Bcb ? -1 : (long)*Bcb),(!Buffer ? -1 : (long)*Buffer));