Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(517)

Side by Side Diff: chrome/installer/mini_installer/decompress.cc

Issue 6693015: Switch out the setup api for using the cabinet API directly.... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <windows.h> // NOLINT
6 #include <fcntl.h> // for _O_* constants
7 #include <fdi.h>
8
9 #include "chrome/installer/mini_installer/decompress.h"
10
11 namespace {
12
13 FNALLOC(Alloc) {
14 return ::HeapAlloc(::GetProcessHeap(), 0, cb);
15 }
16
17 FNFREE(Free) {
18 ::HeapFree(::GetProcessHeap(), 0, pv);
19 }
20
21 char* WideToUtf8(const wchar_t* str) {
amit 2011/03/15 20:54:35 nit: we probably need mini_installer_utils.h/cc fo
tommi (sloooow) - chröme 2011/03/16 02:43:30 Yes, eventually. However right now, we don't need
amit 2011/03/16 15:50:26 That's reasonable.
22 char* ret = NULL;
23 int size = WideCharToMultiByte(CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL);
24 if (size) {
25 ret = reinterpret_cast<char*>(Alloc(size * sizeof(ret[0])));
26 if (ret)
27 WideCharToMultiByte(CP_UTF8, 0, str, -1, ret, size, NULL, NULL);
28 }
29 return ret;
30 }
31
32 wchar_t* Utf8ToWide(const char* str) {
33 wchar_t* ret = NULL;
34 int size = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
35 if (size) {
36 ret = reinterpret_cast<wchar_t*>(Alloc(size * sizeof(ret[0])));
37 if (ret)
38 MultiByteToWideChar(CP_UTF8, 0, str, -1, ret, size);
39 }
40 return ret;
41 }
42
43 template <typename T>
44 class scoped_ptr {
45 public:
46 explicit scoped_ptr(T* a) : a_(a) {
47 }
48 ~scoped_ptr() {
49 if (a_)
50 Free(a_);
51 }
52 operator T*() {
53 return a_;
54 }
55 private:
56 T* a_;
57 };
58
59 FNOPEN(Open) {
60 DWORD access = 0;
61 DWORD disposition = 0;
62
63 if (oflag & _O_RDWR) {
64 access = GENERIC_READ | GENERIC_WRITE;
65 } else if (oflag & _O_WRONLY) {
66 access = GENERIC_WRITE;
67 } else {
68 access = GENERIC_READ;
69 }
70
71 if (oflag & _O_CREAT) {
72 disposition = CREATE_ALWAYS;
73 } else {
74 disposition = OPEN_EXISTING;
75 }
76
77 scoped_ptr<wchar_t> path(Utf8ToWide(pszFile));
78 HANDLE file = CreateFileW(path, access, FILE_SHARE_READ, NULL, disposition,
79 FILE_ATTRIBUTE_NORMAL, NULL);
80 return reinterpret_cast<INT_PTR>(file);
81 }
82
83 FNREAD(Read) {
84 DWORD read = 0;
85 if (!::ReadFile(reinterpret_cast<HANDLE>(hf), pv, cb, &read, NULL))
86 read = static_cast<DWORD>(-1L);
87 return read;
88 }
89
90 FNWRITE(Write) {
91 DWORD written = 0;
92 if (!::WriteFile(reinterpret_cast<HANDLE>(hf), pv, cb, &written, NULL))
93 written = static_cast<DWORD>(-1L);
94 return written;
95 }
96
97 FNCLOSE(Close) {
98 return ::CloseHandle(reinterpret_cast<HANDLE>(hf)) ? 0 : -1;
99 }
100
101 FNSEEK(Seek) {
102 return ::SetFilePointer(reinterpret_cast<HANDLE>(hf), dist, NULL, seektype);
103 }
104
105 FNFDINOTIFY(Notify) {
106 INT_PTR result = 0;
107
108 switch (fdint) {
109 case fdintCOPY_FILE: {
110 // Since we will only ever be decompressing a single file at a time
111 // we take a shortcut and provide a pointer to the wide destination file
112 // of the file we want to write. This way we don't have to bother with
113 // utf8/wide conversion and concatenation of directory and file name.
114 const wchar_t* destination = reinterpret_cast<const wchar_t*>(pfdin->pv);
115 result = reinterpret_cast<INT_PTR>(::CreateFileW(destination,
116 GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS,
117 FILE_ATTRIBUTE_NORMAL, NULL));
118 break;
119 }
120
121 case fdintCLOSE_FILE_INFO: {
122 FILETIME file_time;
123 FILETIME local;
124 FILE_BASIC_INFO fbi;
125
126 // Converts MS-DOS date and time values to a file time
127 if (DosDateTimeToFileTime(pfdin->date, pfdin->time, &file_time) &&
128 LocalFileTimeToFileTime(&file_time, &local)) {
129 fbi.CreationTime.LowPart = local.dwLowDateTime;
130 fbi.CreationTime.HighPart = local.dwHighDateTime;
131 fbi.LastWriteTime.QuadPart = -1;
132 fbi.ChangeTime.QuadPart = -1;
133 fbi.LastAccessTime.QuadPart = -1;
134 fbi.FileAttributes = pfdin->attribs;
135 fbi.FileAttributes &= FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN |
136 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_ARCHIVE;
137 SetFileInformationByHandle(reinterpret_cast<HANDLE>(pfdin->hf),
138 FileBasicInfo, &fbi, sizeof(fbi));
139 }
140
141 result = !Close(pfdin->hf);
142 break;
143 }
144
145 case fdintCABINET_INFO:
146 case fdintENUMERATE:
147 // OK. continue as normal.
148 result = 0;
149 break;
150
151 case fdintPARTIAL_FILE:
152 case fdintNEXT_CABINET:
153 default:
154 // Error case.
155 result = -1;
156 break;
157 }
158
159 return result;
160 }
161
162 // Module handle of cabinet.dll
163 HMODULE g_fdi = NULL;
164
165 // API prototypes.
166 typedef HFDI (DIAMONDAPI* FDICreateFn)(PFNALLOC alloc, PFNFREE free,
167 PFNOPEN open, PFNREAD read,
168 PFNWRITE write, PFNCLOSE close,
169 PFNSEEK seek, int cpu_type, PERF perf);
170 typedef BOOL (DIAMONDAPI* FDIDestroyFn)(HFDI fdi);
171 typedef BOOL (DIAMONDAPI* FDICopyFn)(HFDI fdi, char* cab, char* cab_path,
172 int flags, PFNFDINOTIFY notify,
173 PFNFDIDECRYPT decrypt, void* context);
174 FDICreateFn g_FDICreate = NULL;
175 FDIDestroyFn g_FDIDestroy = NULL;
176 FDICopyFn g_FDICopy = NULL;
177
178 bool InitializeFdi() {
179 if (!g_fdi) {
180 // This DLL should be available on all supported versions of Windows.
181 g_fdi = ::LoadLibraryW(L"cabinet.dll");
amit 2011/03/15 20:54:35 shouldn't this be loaded from a known path, to pre
tommi (sloooow) - chröme 2011/03/16 02:43:30 We don't have a lib for cabinet.dll but this is ef
amit 2011/03/16 15:50:26 sounds good
tommi (sloooow) - chröme 2011/03/16 20:22:20 Done.
182 g_FDICreate =
183 reinterpret_cast<FDICreateFn>(::GetProcAddress(g_fdi, "FDICreate"));
184 g_FDIDestroy =
185 reinterpret_cast<FDIDestroyFn>(::GetProcAddress(g_fdi, "FDIDestroy"));
186 g_FDICopy =
187 reinterpret_cast<FDICopyFn>(::GetProcAddress(g_fdi, "FDICopy"));
188 }
189
190 return g_FDICreate && g_FDIDestroy && g_FDICopy;
191 }
192
193 } // namespace
194
195 namespace mini_installer {
196
197 bool Expand(wchar_t* source, const wchar_t* destination) {
198 if (!InitializeFdi())
199 return false;
200
201 // Start by splitting up the source path and convert to utf8 since the
202 // cabinet API doesn't support wide strings.
203 wchar_t* source_name = source + lstrlenW(source);
204 while (source_name > source && *source_name != L'\\')
205 --source_name;
206 if (source_name == source)
207 return false;
208
209 // Convert the name to utf8.
210 source_name++;
211 scoped_ptr<char> source_name_utf8(WideToUtf8(source_name));
212 // The directory part is assumed to have a trailing backslash.
213 wchar_t save = source_name[0];
214 *source_name = L'\0';
215 scoped_ptr<char> source_path_utf8(WideToUtf8(source));
216 *source_name = save;
217
218 scoped_ptr<char> dest_utf8(WideToUtf8(destination));
219 if (!dest_utf8 || !source_name_utf8 || !source_path_utf8)
220 return false;
221
222 bool success = false;
223
224 ERF erf = {0};
225 HFDI fdi = g_FDICreate(&Alloc, &Free, &Open, &Read, &Write, &Close, &Seek,
226 cpuUNKNOWN, &erf);
227 if (fdi) {
228 if (g_FDICopy(fdi, source_name_utf8, source_path_utf8, 0,
229 &Notify, NULL, const_cast<wchar_t*>(destination))) {
230 success = true;
231 }
232 g_FDIDestroy(fdi);
233 }
234
235 return success;
236 }
237
238 } // namespace mini_installer
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698