]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.c
ShellPkg: Add checking for memory allocation and pointer returns from functions.
[mirror_edk2.git] / ShellPkg / Library / UefiShellDebug1CommandsLib / HexEdit / FileImage.c
1 /** @file
2 Functions to deal with file buffer.
3
4 Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "HexEditor.h"
16
17 extern EFI_HANDLE HImageHandleBackup;
18 extern HEFI_EDITOR_BUFFER_IMAGE HBufferImage;
19
20 extern BOOLEAN HBufferImageNeedRefresh;
21 extern BOOLEAN HBufferImageOnlyLineNeedRefresh;
22 extern BOOLEAN HBufferImageMouseNeedRefresh;
23
24 extern HEFI_EDITOR_GLOBAL_EDITOR HMainEditor;
25
26 HEFI_EDITOR_FILE_IMAGE HFileImage;
27 HEFI_EDITOR_FILE_IMAGE HFileImageBackupVar;
28
29 //
30 // for basic initialization of HFileImage
31 //
32 HEFI_EDITOR_BUFFER_IMAGE HFileImageConst = {
33 NULL,
34 0,
35 FALSE
36 };
37
38 /**
39 Initialization function for HFileImage
40
41 @retval EFI_SUCCESS The operation was successful.
42 **/
43 EFI_STATUS
44 HFileImageInit (
45 VOID
46 )
47 {
48 //
49 // basically initialize the HFileImage
50 //
51 CopyMem (&HFileImage, &HFileImageConst, sizeof (HFileImage));
52
53 CopyMem (
54 &HFileImageBackupVar,
55 &HFileImageConst,
56 sizeof (HFileImageBackupVar)
57 );
58
59 return EFI_SUCCESS;
60 }
61
62 /**
63 Backup function for HFileImage. Only a few fields need to be backup.
64 This is for making the file buffer refresh as few as possible.
65
66 @retval EFI_SUCCESS The operation was successful.
67 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
68 **/
69 EFI_STATUS
70 HFileImageBackup (
71 VOID
72 )
73 {
74 SHELL_FREE_NON_NULL (HFileImageBackupVar.FileName);
75 HFileImageBackupVar.FileName = CatSPrint(NULL, L"%s", HFileImage.FileName);
76 if (HFileImageBackupVar.FileName == NULL) {
77 return EFI_OUT_OF_RESOURCES;
78 }
79
80 return EFI_SUCCESS;
81 }
82
83 /**
84 Cleanup function for HFileImage.
85
86 @retval EFI_SUCCESS The operation was successful.
87 **/
88 EFI_STATUS
89 HFileImageCleanup (
90 VOID
91 )
92 {
93
94 SHELL_FREE_NON_NULL (HFileImage.FileName);
95 SHELL_FREE_NON_NULL (HFileImageBackupVar.FileName);
96
97 return EFI_SUCCESS;
98 }
99
100 /**
101 Set FileName field in HFileImage
102
103 @param[in] Str File name to set.
104
105 @retval EFI_SUCCESS The operation was successful.
106 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
107 **/
108 EFI_STATUS
109 HFileImageSetFileName (
110 IN CONST CHAR16 *Str
111 )
112 {
113 UINTN Size;
114 UINTN Index;
115
116 //
117 // free the old file name
118 //
119 SHELL_FREE_NON_NULL (HFileImage.FileName);
120
121 Size = StrLen (Str);
122
123 HFileImage.FileName = AllocateZeroPool (2 * (Size + 1));
124 if (HFileImage.FileName == NULL) {
125 return EFI_OUT_OF_RESOURCES;
126 }
127
128 for (Index = 0; Index < Size; Index++) {
129 HFileImage.FileName[Index] = Str[Index];
130 }
131
132 HFileImage.FileName[Size] = L'\0';
133
134 return EFI_SUCCESS;
135 }
136
137 /**
138 Read a file from disk into HBufferImage.
139
140 @param[in] FileName filename to read.
141 @param[in] Recover if is for recover, no information print.
142
143 @retval EFI_SUCCESS The operation was successful.
144 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
145 @retval EFI_LOAD_ERROR A load error occured.
146 **/
147 EFI_STATUS
148 HFileImageRead (
149 IN CONST CHAR16 *FileName,
150 IN BOOLEAN Recover
151 )
152 {
153 HEFI_EDITOR_LINE *Line;
154 UINT8 *Buffer;
155 CHAR16 *UnicodeBuffer;
156 EFI_STATUS Status;
157
158 //
159 // variable initialization
160 //
161 Line = NULL;
162
163 //
164 // in this function, when you return error ( except EFI_OUT_OF_RESOURCES )
165 // you should set status string
166 // since this function maybe called before the editorhandleinput loop
167 // so any error will cause editor return
168 // so if you want to print the error status
169 // you should set the status string
170 //
171 Status = ReadFileIntoBuffer (FileName, (VOID**)&Buffer, &HFileImage.Size, &HFileImage.ReadOnly);
172 if (EFI_ERROR(Status) || Buffer == NULL) {
173 UnicodeBuffer = CatSPrint(NULL, L"Read error on file &s: %r", FileName, Status);
174 if (UnicodeBuffer == NULL) {
175 SHELL_FREE_NON_NULL(Buffer);
176 return EFI_OUT_OF_RESOURCES;
177 }
178
179 StatusBarSetStatusString (UnicodeBuffer);
180 FreePool (UnicodeBuffer);
181 return EFI_OUT_OF_RESOURCES;
182 }
183
184 HFileImageSetFileName (FileName);
185
186 //
187 // free the old lines
188 //
189 HBufferImageFree ();
190
191 Status = HBufferImageBufferToList (Buffer, HFileImage.Size);
192 SHELL_FREE_NON_NULL (Buffer);
193 if (EFI_ERROR (Status)) {
194 StatusBarSetStatusString (L"Error parsing file.");
195 return Status;
196 }
197
198 HBufferImage.DisplayPosition.Row = 2;
199 HBufferImage.DisplayPosition.Column = 10;
200 HBufferImage.MousePosition.Row = 2;
201 HBufferImage.MousePosition.Column = 10;
202 HBufferImage.LowVisibleRow = 1;
203 HBufferImage.HighBits = TRUE;
204 HBufferImage.BufferPosition.Row = 1;
205 HBufferImage.BufferPosition.Column = 1;
206 HBufferImage.BufferType = FileTypeFileBuffer;
207
208 if (!Recover) {
209 UnicodeBuffer = CatSPrint(NULL, L"%d Lines Read", HBufferImage.NumLines);
210 if (UnicodeBuffer == NULL) {
211 SHELL_FREE_NON_NULL(Buffer);
212 return EFI_OUT_OF_RESOURCES;
213 }
214
215 StatusBarSetStatusString (UnicodeBuffer);
216 FreePool (UnicodeBuffer);
217
218 HMainEditor.SelectStart = 0;
219 HMainEditor.SelectEnd = 0;
220 }
221
222 //
223 // has line
224 //
225 if (HBufferImage.Lines != 0) {
226 HBufferImage.CurrentLine = CR (HBufferImage.ListHead->ForwardLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
227 } else {
228 //
229 // create a dummy line
230 //
231 Line = HBufferImageCreateLine ();
232 if (Line == NULL) {
233 SHELL_FREE_NON_NULL(Buffer);
234 return EFI_OUT_OF_RESOURCES;
235 }
236
237 HBufferImage.CurrentLine = Line;
238 }
239
240 HBufferImage.Modified = FALSE;
241 HBufferImageNeedRefresh = TRUE;
242 HBufferImageOnlyLineNeedRefresh = FALSE;
243 HBufferImageMouseNeedRefresh = TRUE;
244
245 return EFI_SUCCESS;
246 }
247
248 /**
249 Save lines in HBufferImage to disk.
250
251 @param[in] FileName The file name.
252
253 @retval EFI_SUCCESS The operation was successful.
254 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
255 @retval EFI_LOAD_ERROR A load error occured.
256 **/
257 EFI_STATUS
258 HFileImageSave (
259 IN CHAR16 *FileName
260 )
261 {
262
263 LIST_ENTRY *Link;
264 HEFI_EDITOR_LINE *Line;
265 CHAR16 *Str;
266 EFI_STATUS Status;
267 UINTN NumLines;
268 SHELL_FILE_HANDLE FileHandle;
269 UINTN TotalSize;
270 UINT8 *Buffer;
271 UINT8 *Ptr;
272 EDIT_FILE_TYPE BufferTypeBackup;
273
274 BufferTypeBackup = HBufferImage.BufferType;
275 HBufferImage.BufferType = FileTypeFileBuffer;
276
277 //
278 // if is the old file
279 //
280 if (HFileImage.FileName != NULL && FileName != NULL && StrCmp (FileName, HFileImage.FileName) == 0) {
281 //
282 // check whether file exists on disk
283 //
284 if (ShellIsFile(FileName) == EFI_SUCCESS) {
285 //
286 // current file exists on disk
287 // so if not modified, then not save
288 //
289 if (HBufferImage.Modified == FALSE) {
290 return EFI_SUCCESS;
291 }
292 //
293 // if file is read-only, set error
294 //
295 if (HFileImage.ReadOnly == TRUE) {
296 StatusBarSetStatusString (L"Read Only File Can Not Be Saved");
297 return EFI_SUCCESS;
298 }
299 }
300 }
301
302 if (ShellIsDirectory(FileName) == EFI_SUCCESS) {
303 StatusBarSetStatusString (L"Directory Can Not Be Saved");
304 return EFI_LOAD_ERROR;
305 }
306
307 Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0);
308
309 if (!EFI_ERROR (Status)) {
310 //
311 // the file exits, delete it
312 //
313 Status = ShellDeleteFile (&FileHandle);
314 if (EFI_ERROR (Status) || Status == EFI_WARN_DELETE_FAILURE) {
315 StatusBarSetStatusString (L"Write File Failed");
316 return EFI_LOAD_ERROR;
317 }
318 }
319
320 //
321 // write all the lines back to disk
322 //
323 NumLines = 0;
324 TotalSize = 0;
325 for (Link = HBufferImage.ListHead->ForwardLink; Link != HBufferImage.ListHead; Link = Link->ForwardLink) {
326 Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
327
328 if (Line->Size != 0) {
329 TotalSize += Line->Size;
330 }
331 //
332 // end of if Line -> Size != 0
333 //
334 NumLines++;
335 }
336 //
337 // end of for Link
338 //
339 Buffer = AllocateZeroPool (TotalSize);
340 if (Buffer == NULL) {
341 return EFI_OUT_OF_RESOURCES;
342 }
343
344 Ptr = Buffer;
345 for (Link = HBufferImage.ListHead->ForwardLink; Link != HBufferImage.ListHead; Link = Link->ForwardLink) {
346 Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
347
348 if (Line->Size != 0) {
349 CopyMem (Ptr, Line->Buffer, Line->Size);
350 Ptr += Line->Size;
351 }
352 //
353 // end of if Line -> Size != 0
354 //
355 }
356
357
358 Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0);
359
360 if (EFI_ERROR (Status)) {
361 StatusBarSetStatusString (L"Create File Failed");
362 return EFI_LOAD_ERROR;
363 }
364
365 Status = ShellWriteFile (FileHandle, &TotalSize, Buffer);
366 FreePool (Buffer);
367 if (EFI_ERROR (Status)) {
368 ShellDeleteFile (&FileHandle);
369 return EFI_LOAD_ERROR;
370 }
371
372 ShellCloseFile(&FileHandle);
373
374 HBufferImage.Modified = FALSE;
375
376 //
377 // set status string
378 //
379 Str = CatSPrint(NULL, L"%d Lines Wrote", NumLines);
380 StatusBarSetStatusString (Str);
381 FreePool (Str);
382
383 //
384 // now everything is ready , you can set the new file name to filebuffer
385 //
386 if ((BufferTypeBackup != FileTypeFileBuffer && FileName != NULL) ||
387 (FileName != NULL && HFileImage.FileName != NULL && StringNoCaseCompare (&FileName, &HFileImage.FileName) != 0)){
388 //
389 // not the same
390 //
391 HFileImageSetFileName (FileName);
392 if (HFileImage.FileName == NULL) {
393 return EFI_OUT_OF_RESOURCES;
394 }
395 }
396
397 HFileImage.ReadOnly = FALSE;
398
399 return EFI_SUCCESS;
400 }