Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenfiles.c
Go to the documentation of this file.
00001 /* 00002 * Advpack file functions 00003 * 00004 * Copyright 2006 James Hawkins 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00019 */ 00020 00021 #include <stdarg.h> 00022 #include <stdlib.h> 00023 00024 #include "windef.h" 00025 #include "winbase.h" 00026 #include "winuser.h" 00027 #include "winreg.h" 00028 #include "winver.h" 00029 #include "winternl.h" 00030 #include "setupapi.h" 00031 #include "advpub.h" 00032 #include "fdi.h" 00033 #include "wine/debug.h" 00034 #include "wine/unicode.h" 00035 #include "advpack_private.h" 00036 00037 WINE_DEFAULT_DEBUG_CHANNEL(advpack); 00038 00039 /* converts an ansi double null-terminated list to a unicode list */ 00040 static LPWSTR ansi_to_unicode_list(LPCSTR ansi_list) 00041 { 00042 DWORD len, wlen = 0; 00043 LPWSTR list; 00044 LPCSTR ptr = ansi_list; 00045 00046 while (*ptr) ptr += lstrlenA(ptr) + 1; 00047 len = ptr + 1 - ansi_list; 00048 wlen = MultiByteToWideChar(CP_ACP, 0, ansi_list, len, NULL, 0); 00049 list = HeapAlloc(GetProcessHeap(), 0, wlen * sizeof(WCHAR)); 00050 MultiByteToWideChar(CP_ACP, 0, ansi_list, len, list, wlen); 00051 return list; 00052 } 00053 00054 /*********************************************************************** 00055 * AddDelBackupEntryA (ADVPACK.@) 00056 * 00057 * See AddDelBackupEntryW. 00058 */ 00059 HRESULT WINAPI AddDelBackupEntryA(LPCSTR lpcszFileList, LPCSTR lpcszBackupDir, 00060 LPCSTR lpcszBaseName, DWORD dwFlags) 00061 { 00062 UNICODE_STRING backupdir, basename; 00063 LPWSTR filelist; 00064 LPCWSTR backup; 00065 HRESULT res; 00066 00067 TRACE("(%s, %s, %s, %d)\n", debugstr_a(lpcszFileList), 00068 debugstr_a(lpcszBackupDir), debugstr_a(lpcszBaseName), dwFlags); 00069 00070 if (lpcszFileList) 00071 filelist = ansi_to_unicode_list(lpcszFileList); 00072 else 00073 filelist = NULL; 00074 00075 RtlCreateUnicodeStringFromAsciiz(&backupdir, lpcszBackupDir); 00076 RtlCreateUnicodeStringFromAsciiz(&basename, lpcszBaseName); 00077 00078 if (lpcszBackupDir) 00079 backup = backupdir.Buffer; 00080 else 00081 backup = NULL; 00082 00083 res = AddDelBackupEntryW(filelist, backup, basename.Buffer, dwFlags); 00084 00085 HeapFree(GetProcessHeap(), 0, filelist); 00086 00087 RtlFreeUnicodeString(&backupdir); 00088 RtlFreeUnicodeString(&basename); 00089 00090 return res; 00091 } 00092 00093 /*********************************************************************** 00094 * AddDelBackupEntryW (ADVPACK.@) 00095 * 00096 * Either appends the files in the file list to the backup section of 00097 * the specified INI, or deletes the entries from the INI file. 00098 * 00099 * PARAMS 00100 * lpcszFileList [I] NULL-separated list of filenames. 00101 * lpcszBackupDir [I] Path of the backup directory. 00102 * lpcszBaseName [I] Basename of the INI file. 00103 * dwFlags [I] AADBE_ADD_ENTRY adds the entries in the file list 00104 * to the INI file, while AADBE_DEL_ENTRY removes 00105 * the entries from the INI file. 00106 * 00107 * RETURNS 00108 * S_OK in all cases. 00109 * 00110 * NOTES 00111 * If the INI file does not exist before adding entries to it, the file 00112 * will be created. 00113 * 00114 * If lpcszBackupDir is NULL, the INI file is assumed to exist in 00115 * c:\windows or created there if it does not exist. 00116 */ 00117 HRESULT WINAPI AddDelBackupEntryW(LPCWSTR lpcszFileList, LPCWSTR lpcszBackupDir, 00118 LPCWSTR lpcszBaseName, DWORD dwFlags) 00119 { 00120 WCHAR szIniPath[MAX_PATH]; 00121 LPCWSTR szString = NULL; 00122 00123 static const WCHAR szBackupEntry[] = { 00124 '-','1',',','0',',','0',',','0',',','0',',','0',',','-','1',0 00125 }; 00126 00127 static const WCHAR backslash[] = {'\\',0}; 00128 static const WCHAR ini[] = {'.','i','n','i',0}; 00129 static const WCHAR backup[] = {'b','a','c','k','u','p',0}; 00130 00131 TRACE("(%s, %s, %s, %d)\n", debugstr_w(lpcszFileList), 00132 debugstr_w(lpcszBackupDir), debugstr_w(lpcszBaseName), dwFlags); 00133 00134 if (!lpcszFileList || !*lpcszFileList) 00135 return S_OK; 00136 00137 if (lpcszBackupDir) 00138 lstrcpyW(szIniPath, lpcszBackupDir); 00139 else 00140 GetWindowsDirectoryW(szIniPath, MAX_PATH); 00141 00142 lstrcatW(szIniPath, backslash); 00143 lstrcatW(szIniPath, lpcszBaseName); 00144 lstrcatW(szIniPath, ini); 00145 00146 SetFileAttributesW(szIniPath, FILE_ATTRIBUTE_NORMAL); 00147 00148 if (dwFlags & AADBE_ADD_ENTRY) 00149 szString = szBackupEntry; 00150 else if (dwFlags & AADBE_DEL_ENTRY) 00151 szString = NULL; 00152 00153 /* add or delete the INI entries */ 00154 while (*lpcszFileList) 00155 { 00156 WritePrivateProfileStringW(backup, lpcszFileList, szString, szIniPath); 00157 lpcszFileList += lstrlenW(lpcszFileList) + 1; 00158 } 00159 00160 /* hide the INI file */ 00161 SetFileAttributesW(szIniPath, FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN); 00162 00163 return S_OK; 00164 } 00165 00166 /* FIXME: this is only for the local case, X:\ */ 00167 #define ROOT_LENGTH 3 00168 00169 static UINT CALLBACK pQuietQueueCallback(PVOID Context, UINT Notification, 00170 UINT_PTR Param1, UINT_PTR Param2) 00171 { 00172 return 1; 00173 } 00174 00175 static UINT CALLBACK pQueueCallback(PVOID Context, UINT Notification, 00176 UINT_PTR Param1, UINT_PTR Param2) 00177 { 00178 /* only be verbose for error notifications */ 00179 if (!Notification || 00180 Notification == SPFILENOTIFY_RENAMEERROR || 00181 Notification == SPFILENOTIFY_DELETEERROR || 00182 Notification == SPFILENOTIFY_COPYERROR) 00183 { 00184 return SetupDefaultQueueCallbackW(Context, Notification, 00185 Param1, Param2); 00186 } 00187 00188 return 1; 00189 } 00190 00191 /*********************************************************************** 00192 * AdvInstallFileA (ADVPACK.@) 00193 * 00194 * See AdvInstallFileW. 00195 */ 00196 HRESULT WINAPI AdvInstallFileA(HWND hwnd, LPCSTR lpszSourceDir, LPCSTR lpszSourceFile, 00197 LPCSTR lpszDestDir, LPCSTR lpszDestFile, 00198 DWORD dwFlags, DWORD dwReserved) 00199 { 00200 UNICODE_STRING sourcedir, sourcefile; 00201 UNICODE_STRING destdir, destfile; 00202 HRESULT res; 00203 00204 TRACE("(%p, %s, %s, %s, %s, %d, %d)\n", hwnd, debugstr_a(lpszSourceDir), 00205 debugstr_a(lpszSourceFile), debugstr_a(lpszDestDir), 00206 debugstr_a(lpszDestFile), dwFlags, dwReserved); 00207 00208 if (!lpszSourceDir || !lpszSourceFile || !lpszDestDir) 00209 return E_INVALIDARG; 00210 00211 RtlCreateUnicodeStringFromAsciiz(&sourcedir, lpszSourceDir); 00212 RtlCreateUnicodeStringFromAsciiz(&sourcefile, lpszSourceFile); 00213 RtlCreateUnicodeStringFromAsciiz(&destdir, lpszDestDir); 00214 RtlCreateUnicodeStringFromAsciiz(&destfile, lpszDestFile); 00215 00216 res = AdvInstallFileW(hwnd, sourcedir.Buffer, sourcefile.Buffer, 00217 destdir.Buffer, destfile.Buffer, dwFlags, dwReserved); 00218 00219 RtlFreeUnicodeString(&sourcedir); 00220 RtlFreeUnicodeString(&sourcefile); 00221 RtlFreeUnicodeString(&destdir); 00222 RtlFreeUnicodeString(&destfile); 00223 00224 return res; 00225 } 00226 00227 /*********************************************************************** 00228 * AdvInstallFileW (ADVPACK.@) 00229 * 00230 * Copies a file from the source to a destination. 00231 * 00232 * PARAMS 00233 * hwnd [I] Handle to the window used for messages. 00234 * lpszSourceDir [I] Source directory. 00235 * lpszSourceFile [I] Source filename. 00236 * lpszDestDir [I] Destination directory. 00237 * lpszDestFile [I] Optional destination filename. 00238 * dwFlags [I] See advpub.h. 00239 * dwReserved [I] Reserved. Must be 0. 00240 * 00241 * RETURNS 00242 * Success: S_OK. 00243 * Failure: E_FAIL. 00244 * 00245 * NOTES 00246 * If lpszDestFile is NULL, the destination filename is the same as 00247 * lpszSourceFIle. 00248 */ 00249 HRESULT WINAPI AdvInstallFileW(HWND hwnd, LPCWSTR lpszSourceDir, LPCWSTR lpszSourceFile, 00250 LPCWSTR lpszDestDir, LPCWSTR lpszDestFile, 00251 DWORD dwFlags, DWORD dwReserved) 00252 { 00253 PSP_FILE_CALLBACK_W pFileCallback; 00254 LPWSTR szDestFilename; 00255 LPCWSTR szPath; 00256 WCHAR szRootPath[ROOT_LENGTH]; 00257 DWORD dwLen, dwLastError; 00258 HSPFILEQ fileQueue; 00259 PVOID pContext; 00260 00261 TRACE("(%p, %s, %s, %s, %s, %d, %d)\n", hwnd, debugstr_w(lpszSourceDir), 00262 debugstr_w(lpszSourceFile), debugstr_w(lpszDestDir), 00263 debugstr_w(lpszDestFile), dwFlags, dwReserved); 00264 00265 if (!lpszSourceDir || !lpszSourceFile || !lpszDestDir) 00266 return E_INVALIDARG; 00267 00268 fileQueue = SetupOpenFileQueue(); 00269 if (fileQueue == INVALID_HANDLE_VALUE) 00270 return HRESULT_FROM_WIN32(GetLastError()); 00271 00272 pContext = NULL; 00273 dwLastError = ERROR_SUCCESS; 00274 00275 lstrcpynW(szRootPath, lpszSourceDir, ROOT_LENGTH); 00276 szPath = lpszSourceDir + ROOT_LENGTH; 00277 00278 /* use lpszSourceFile as destination filename if lpszDestFile is NULL */ 00279 if (lpszDestFile) 00280 { 00281 dwLen = lstrlenW(lpszDestFile); 00282 szDestFilename = HeapAlloc(GetProcessHeap(), 0, (dwLen+1) * sizeof(WCHAR)); 00283 lstrcpyW(szDestFilename, lpszDestFile); 00284 } 00285 else 00286 { 00287 dwLen = lstrlenW(lpszSourceFile); 00288 szDestFilename = HeapAlloc(GetProcessHeap(), 0, (dwLen+1) * sizeof(WCHAR)); 00289 lstrcpyW(szDestFilename, lpszSourceFile); 00290 } 00291 00292 /* add the file copy operation to the setup queue */ 00293 if (!SetupQueueCopyW(fileQueue, szRootPath, szPath, lpszSourceFile, NULL, 00294 NULL, lpszDestDir, szDestFilename, dwFlags)) 00295 { 00296 dwLastError = GetLastError(); 00297 goto done; 00298 } 00299 00300 pContext = SetupInitDefaultQueueCallbackEx(hwnd, INVALID_HANDLE_VALUE, 00301 0, 0, NULL); 00302 if (!pContext) 00303 { 00304 dwLastError = GetLastError(); 00305 goto done; 00306 } 00307 00308 /* don't output anything for AIF_QUIET */ 00309 if (dwFlags & AIF_QUIET) 00310 pFileCallback = pQuietQueueCallback; 00311 else 00312 pFileCallback = pQueueCallback; 00313 00314 /* perform the file copy */ 00315 if (!SetupCommitFileQueueW(hwnd, fileQueue, pFileCallback, pContext)) 00316 { 00317 dwLastError = GetLastError(); 00318 goto done; 00319 } 00320 00321 done: 00322 SetupTermDefaultQueueCallback(pContext); 00323 SetupCloseFileQueue(fileQueue); 00324 00325 HeapFree(GetProcessHeap(), 0, szDestFilename); 00326 00327 return HRESULT_FROM_WIN32(dwLastError); 00328 } 00329 00330 static HRESULT DELNODE_recurse_dirtree(LPWSTR fname, DWORD flags) 00331 { 00332 DWORD fattrs = GetFileAttributesW(fname); 00333 HRESULT ret = E_FAIL; 00334 00335 static const WCHAR asterisk[] = {'*',0}; 00336 static const WCHAR dot[] = {'.',0}; 00337 static const WCHAR dotdot[] = {'.','.',0}; 00338 00339 if (fattrs & FILE_ATTRIBUTE_DIRECTORY) 00340 { 00341 HANDLE hFindFile; 00342 WIN32_FIND_DATAW w32fd; 00343 BOOL done = TRUE; 00344 int fname_len = lstrlenW(fname); 00345 00346 /* Generate a path with wildcard suitable for iterating */ 00347 if (fname_len && fname[fname_len-1] != '\\') fname[fname_len++] = '\\'; 00348 lstrcpyW(fname + fname_len, asterisk); 00349 00350 if ((hFindFile = FindFirstFileW(fname, &w32fd)) != INVALID_HANDLE_VALUE) 00351 { 00352 /* Iterate through the files in the directory */ 00353 for (done = FALSE; !done; done = !FindNextFileW(hFindFile, &w32fd)) 00354 { 00355 TRACE("%s\n", debugstr_w(w32fd.cFileName)); 00356 if (lstrcmpW(dot, w32fd.cFileName) != 0 && 00357 lstrcmpW(dotdot, w32fd.cFileName) != 0) 00358 { 00359 lstrcpyW(fname + fname_len, w32fd.cFileName); 00360 if (DELNODE_recurse_dirtree(fname, flags) != S_OK) 00361 { 00362 break; /* Failure */ 00363 } 00364 } 00365 } 00366 FindClose(hFindFile); 00367 } 00368 00369 /* We're done with this directory, so restore the old path without wildcard */ 00370 *(fname + fname_len) = '\0'; 00371 00372 if (done) 00373 { 00374 TRACE("%s: directory\n", debugstr_w(fname)); 00375 if (SetFileAttributesW(fname, FILE_ATTRIBUTE_NORMAL) && RemoveDirectoryW(fname)) 00376 { 00377 ret = S_OK; 00378 } 00379 } 00380 } 00381 else 00382 { 00383 TRACE("%s: file\n", debugstr_w(fname)); 00384 if (SetFileAttributesW(fname, FILE_ATTRIBUTE_NORMAL) && DeleteFileW(fname)) 00385 { 00386 ret = S_OK; 00387 } 00388 } 00389 00390 return ret; 00391 } 00392 00393 /*********************************************************************** 00394 * DelNodeA (ADVPACK.@) 00395 * 00396 * See DelNodeW. 00397 */ 00398 HRESULT WINAPI DelNodeA(LPCSTR pszFileOrDirName, DWORD dwFlags) 00399 { 00400 UNICODE_STRING fileordirname; 00401 HRESULT res; 00402 00403 TRACE("(%s, %d)\n", debugstr_a(pszFileOrDirName), dwFlags); 00404 00405 RtlCreateUnicodeStringFromAsciiz(&fileordirname, pszFileOrDirName); 00406 00407 res = DelNodeW(fileordirname.Buffer, dwFlags); 00408 00409 RtlFreeUnicodeString(&fileordirname); 00410 00411 return res; 00412 } 00413 00414 /*********************************************************************** 00415 * DelNodeW (ADVPACK.@) 00416 * 00417 * Deletes a file or directory 00418 * 00419 * PARAMS 00420 * pszFileOrDirName [I] Name of file or directory to delete 00421 * dwFlags [I] Flags; see include/advpub.h 00422 * 00423 * RETURNS 00424 * Success: S_OK 00425 * Failure: E_FAIL 00426 * 00427 * BUGS 00428 * - Ignores flags 00429 * - Native version apparently does a lot of checking to make sure 00430 * we're not trying to delete a system directory etc. 00431 */ 00432 HRESULT WINAPI DelNodeW(LPCWSTR pszFileOrDirName, DWORD dwFlags) 00433 { 00434 WCHAR fname[MAX_PATH]; 00435 HRESULT ret = E_FAIL; 00436 00437 TRACE("(%s, %d)\n", debugstr_w(pszFileOrDirName), dwFlags); 00438 00439 if (dwFlags) 00440 FIXME("Flags ignored!\n"); 00441 00442 if (pszFileOrDirName && *pszFileOrDirName) 00443 { 00444 lstrcpyW(fname, pszFileOrDirName); 00445 00446 /* TODO: Should check for system directory deletion etc. here */ 00447 00448 ret = DELNODE_recurse_dirtree(fname, dwFlags); 00449 } 00450 00451 return ret; 00452 } 00453 00454 /*********************************************************************** 00455 * DelNodeRunDLL32A (ADVPACK.@) 00456 * 00457 * See DelNodeRunDLL32W. 00458 */ 00459 HRESULT WINAPI DelNodeRunDLL32A(HWND hWnd, HINSTANCE hInst, LPSTR cmdline, INT show) 00460 { 00461 UNICODE_STRING params; 00462 HRESULT hr; 00463 00464 TRACE("(%p, %p, %s, %i)\n", hWnd, hInst, debugstr_a(cmdline), show); 00465 00466 RtlCreateUnicodeStringFromAsciiz(¶ms, cmdline); 00467 00468 hr = DelNodeRunDLL32W(hWnd, hInst, params.Buffer, show); 00469 00470 RtlFreeUnicodeString(¶ms); 00471 00472 return hr; 00473 } 00474 00475 /*********************************************************************** 00476 * DelNodeRunDLL32W (ADVPACK.@) 00477 * 00478 * Deletes a file or directory, WinMain style. 00479 * 00480 * PARAMS 00481 * hWnd [I] Handle to the window used for the display. 00482 * hInst [I] Instance of the process. 00483 * cmdline [I] Contains parameters in the order FileOrDirName,Flags. 00484 * show [I] How the window should be shown. 00485 * 00486 * RETURNS 00487 * Success: S_OK. 00488 * Failure: E_FAIL. 00489 */ 00490 HRESULT WINAPI DelNodeRunDLL32W(HWND hWnd, HINSTANCE hInst, LPWSTR cmdline, INT show) 00491 { 00492 LPWSTR szFilename, szFlags; 00493 LPWSTR cmdline_copy, cmdline_ptr; 00494 DWORD dwFlags = 0; 00495 HRESULT res; 00496 00497 TRACE("(%p, %p, %s, %i)\n", hWnd, hInst, debugstr_w(cmdline), show); 00498 00499 cmdline_copy = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(cmdline) + 1) * sizeof(WCHAR)); 00500 cmdline_ptr = cmdline_copy; 00501 lstrcpyW(cmdline_copy, cmdline); 00502 00503 /* get the parameters at indexes 0 and 1 respectively */ 00504 szFilename = get_parameter(&cmdline_ptr, ','); 00505 szFlags = get_parameter(&cmdline_ptr, ','); 00506 00507 if (szFlags) 00508 dwFlags = atolW(szFlags); 00509 00510 res = DelNodeW(szFilename, dwFlags); 00511 00512 HeapFree(GetProcessHeap(), 0, cmdline_copy); 00513 00514 return res; 00515 } 00516 00517 /* The following definitions were copied from dlls/cabinet/cabinet.h */ 00518 00519 /* SESSION Operation */ 00520 #define EXTRACT_FILLFILELIST 0x00000001 00521 #define EXTRACT_EXTRACTFILES 0x00000002 00522 00523 struct FILELIST{ 00524 LPSTR FileName; 00525 struct FILELIST *next; 00526 BOOL DoExtract; 00527 }; 00528 00529 typedef struct { 00530 INT FileSize; 00531 ERF Error; 00532 struct FILELIST *FileList; 00533 INT FileCount; 00534 INT Operation; 00535 CHAR Destination[MAX_PATH]; 00536 CHAR CurrentFile[MAX_PATH]; 00537 CHAR Reserved[MAX_PATH]; 00538 struct FILELIST *FilterList; 00539 } SESSION; 00540 00541 static HRESULT (WINAPI *pExtract)(SESSION*, LPCSTR); 00542 00543 /* removes legal characters before and after file list, and 00544 * converts the file list to a NULL-separated list 00545 */ 00546 static LPSTR convert_file_list(LPCSTR FileList, DWORD *dwNumFiles) 00547 { 00548 DWORD dwLen; 00549 const char *first = FileList; 00550 const char *last = FileList + strlen(FileList) - 1; 00551 LPSTR szConvertedList, temp; 00552 00553 /* any number of these chars before the list is OK */ 00554 while (first < last && (*first == ' ' || *first == '\t' || *first == ':')) 00555 first++; 00556 00557 /* any number of these chars after the list is OK */ 00558 while (last > first && (*last == ' ' || *last == '\t' || *last == ':')) 00559 last--; 00560 00561 if (first == last) 00562 return NULL; 00563 00564 dwLen = last - first + 3; /* room for double-null termination */ 00565 szConvertedList = HeapAlloc(GetProcessHeap(), 0, dwLen); 00566 lstrcpynA(szConvertedList, first, dwLen - 1); 00567 szConvertedList[dwLen - 1] = '\0'; 00568 00569 /* empty list */ 00570 if (!lstrlenA(szConvertedList)) 00571 { 00572 HeapFree(GetProcessHeap(), 0, szConvertedList); 00573 return NULL; 00574 } 00575 00576 *dwNumFiles = 1; 00577 00578 /* convert the colons to double-null termination */ 00579 temp = szConvertedList; 00580 while (*temp) 00581 { 00582 if (*temp == ':') 00583 { 00584 *temp = '\0'; 00585 (*dwNumFiles)++; 00586 } 00587 00588 temp++; 00589 } 00590 00591 return szConvertedList; 00592 } 00593 00594 static void free_file_node(struct FILELIST *pNode) 00595 { 00596 HeapFree(GetProcessHeap(), 0, pNode->FileName); 00597 HeapFree(GetProcessHeap(), 0, pNode); 00598 } 00599 00600 /* determines whether szFile is in the NULL-separated szFileList */ 00601 static BOOL file_in_list(LPCSTR szFile, LPCSTR szFileList) 00602 { 00603 DWORD dwLen = lstrlenA(szFile); 00604 DWORD dwTestLen; 00605 00606 while (*szFileList) 00607 { 00608 dwTestLen = lstrlenA(szFileList); 00609 00610 if (dwTestLen == dwLen) 00611 { 00612 if (!lstrcmpiA(szFile, szFileList)) 00613 return TRUE; 00614 } 00615 00616 szFileList += dwTestLen + 1; 00617 } 00618 00619 return FALSE; 00620 } 00621 00622 00623 /* returns the number of files that are in both the linked list and szFileList */ 00624 static DWORD fill_file_list(SESSION *session, LPCSTR szCabName, LPCSTR szFileList) 00625 { 00626 DWORD dwNumFound = 0; 00627 struct FILELIST *pNode; 00628 00629 session->Operation |= EXTRACT_FILLFILELIST; 00630 if (pExtract(session, szCabName) != S_OK) 00631 { 00632 session->Operation &= ~EXTRACT_FILLFILELIST; 00633 return -1; 00634 } 00635 00636 pNode = session->FileList; 00637 while (pNode) 00638 { 00639 if (!file_in_list(pNode->FileName, szFileList)) 00640 pNode->DoExtract = FALSE; 00641 else 00642 dwNumFound++; 00643 00644 pNode = pNode->next; 00645 } 00646 00647 session->Operation &= ~EXTRACT_FILLFILELIST; 00648 return dwNumFound; 00649 } 00650 00651 static void free_file_list(SESSION* session) 00652 { 00653 struct FILELIST *next, *curr = session->FileList; 00654 00655 while (curr) 00656 { 00657 next = curr->next; 00658 free_file_node(curr); 00659 curr = next; 00660 } 00661 } 00662 00663 /*********************************************************************** 00664 * ExtractFilesA (ADVPACK.@) 00665 * 00666 * Extracts the specified files from a cab archive into 00667 * a destination directory. 00668 * 00669 * PARAMS 00670 * CabName [I] Filename of the cab archive. 00671 * ExpandDir [I] Destination directory for the extracted files. 00672 * Flags [I] Reserved. 00673 * FileList [I] Optional list of files to extract. See NOTES. 00674 * LReserved [I] Reserved. Must be NULL. 00675 * Reserved [I] Reserved. Must be 0. 00676 * 00677 * RETURNS 00678 * Success: S_OK. 00679 * Failure: E_FAIL. 00680 * 00681 * NOTES 00682 * FileList is a colon-separated list of filenames. If FileList is 00683 * non-NULL, only the files in the list will be extracted from the 00684 * cab file, otherwise all files will be extracted. Any number of 00685 * spaces, tabs, or colons can be before or after the list, but 00686 * the list itself must only be separated by colons. 00687 */ 00688 HRESULT WINAPI ExtractFilesA(LPCSTR CabName, LPCSTR ExpandDir, DWORD Flags, 00689 LPCSTR FileList, LPVOID LReserved, DWORD Reserved) 00690 { 00691 SESSION session; 00692 HMODULE hCabinet; 00693 HRESULT res = S_OK; 00694 DWORD dwFileCount = 0; 00695 DWORD dwFilesFound = 0; 00696 LPSTR szConvertedList = NULL; 00697 00698 TRACE("(%s, %s, %d, %s, %p, %d)\n", debugstr_a(CabName), debugstr_a(ExpandDir), 00699 Flags, debugstr_a(FileList), LReserved, Reserved); 00700 00701 if (!CabName || !ExpandDir) 00702 return E_INVALIDARG; 00703 00704 if (GetFileAttributesA(ExpandDir) == INVALID_FILE_ATTRIBUTES) 00705 return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND); 00706 00707 hCabinet = LoadLibraryA("cabinet.dll"); 00708 if (!hCabinet) 00709 return E_FAIL; 00710 00711 pExtract = (void *)GetProcAddress(hCabinet, "Extract"); 00712 if (!pExtract) 00713 { 00714 res = E_FAIL; 00715 goto done; 00716 } 00717 00718 ZeroMemory(&session, sizeof(SESSION)); 00719 lstrcpyA(session.Destination, ExpandDir); 00720 00721 if (FileList) 00722 { 00723 szConvertedList = convert_file_list(FileList, &dwFileCount); 00724 if (!szConvertedList) 00725 { 00726 res = E_FAIL; 00727 goto done; 00728 } 00729 00730 dwFilesFound = fill_file_list(&session, CabName, szConvertedList); 00731 if (dwFilesFound != dwFileCount) 00732 { 00733 res = E_FAIL; 00734 goto done; 00735 } 00736 } 00737 else 00738 session.Operation |= EXTRACT_FILLFILELIST; 00739 00740 session.Operation |= EXTRACT_EXTRACTFILES; 00741 res = pExtract(&session, CabName); 00742 00743 done: 00744 free_file_list(&session); 00745 FreeLibrary(hCabinet); 00746 HeapFree(GetProcessHeap(), 0, szConvertedList); 00747 00748 return res; 00749 } 00750 00751 /*********************************************************************** 00752 * ExtractFilesW (ADVPACK.@) 00753 * 00754 * Extracts the specified files from a cab archive into 00755 * a destination directory. 00756 * 00757 * PARAMS 00758 * CabName [I] Filename of the cab archive. 00759 * ExpandDir [I] Destination directory for the extracted files. 00760 * Flags [I] Reserved. 00761 * FileList [I] Optional list of files to extract. See NOTES. 00762 * LReserved [I] Reserved. Must be NULL. 00763 * Reserved [I] Reserved. Must be 0. 00764 * 00765 * RETURNS 00766 * Success: S_OK. 00767 * Failure: E_FAIL. 00768 * 00769 * NOTES 00770 * FileList is a colon-separated list of filenames. If FileList is 00771 * non-NULL, only the files in the list will be extracted from the 00772 * cab file, otherwise all files will be extracted. Any number of 00773 * spaces, tabs, or colons can be before or after the list, but 00774 * the list itself must only be separated by colons. 00775 * 00776 * BUGS 00777 * Unimplemented. 00778 */ 00779 HRESULT WINAPI ExtractFilesW(LPCWSTR CabName, LPCWSTR ExpandDir, DWORD Flags, 00780 LPCWSTR FileList, LPVOID LReserved, DWORD Reserved) 00781 { 00782 00783 FIXME("(%s, %s, %d, %s, %p, %d) stub!\n", debugstr_w(CabName), debugstr_w(ExpandDir), 00784 Flags, debugstr_w(FileList), LReserved, Reserved); 00785 00786 return E_FAIL; 00787 } 00788 00789 /*********************************************************************** 00790 * FileSaveMarkNotExistA (ADVPACK.@) 00791 * 00792 * See FileSaveMarkNotExistW. 00793 */ 00794 HRESULT WINAPI FileSaveMarkNotExistA(LPSTR pszFileList, LPSTR pszDir, LPSTR pszBaseName) 00795 { 00796 TRACE("(%s, %s, %s)\n", debugstr_a(pszFileList), 00797 debugstr_a(pszDir), debugstr_a(pszBaseName)); 00798 00799 return AddDelBackupEntryA(pszFileList, pszDir, pszBaseName, AADBE_DEL_ENTRY); 00800 } 00801 00802 /*********************************************************************** 00803 * FileSaveMarkNotExistW (ADVPACK.@) 00804 * 00805 * Marks the files in the file list as not existing so they won't be 00806 * backed up during a save. 00807 * 00808 * PARAMS 00809 * pszFileList [I] NULL-separated list of filenames. 00810 * pszDir [I] Path of the backup directory. 00811 * pszBaseName [I] Basename of the INI file. 00812 * 00813 * RETURNS 00814 * Success: S_OK. 00815 * Failure: E_FAIL. 00816 */ 00817 HRESULT WINAPI FileSaveMarkNotExistW(LPWSTR pszFileList, LPWSTR pszDir, LPWSTR pszBaseName) 00818 { 00819 TRACE("(%s, %s, %s)\n", debugstr_w(pszFileList), 00820 debugstr_w(pszDir), debugstr_w(pszBaseName)); 00821 00822 return AddDelBackupEntryW(pszFileList, pszDir, pszBaseName, AADBE_DEL_ENTRY); 00823 } 00824 00825 /*********************************************************************** 00826 * FileSaveRestoreA (ADVPACK.@) 00827 * 00828 * See FileSaveRestoreW. 00829 */ 00830 HRESULT WINAPI FileSaveRestoreA(HWND hDlg, LPSTR pszFileList, LPSTR pszDir, 00831 LPSTR pszBaseName, DWORD dwFlags) 00832 { 00833 UNICODE_STRING filelist, dir, basename; 00834 HRESULT hr; 00835 00836 TRACE("(%p, %s, %s, %s, %d)\n", hDlg, debugstr_a(pszFileList), 00837 debugstr_a(pszDir), debugstr_a(pszBaseName), dwFlags); 00838 00839 RtlCreateUnicodeStringFromAsciiz(&filelist, pszFileList); 00840 RtlCreateUnicodeStringFromAsciiz(&dir, pszDir); 00841 RtlCreateUnicodeStringFromAsciiz(&basename, pszBaseName); 00842 00843 hr = FileSaveRestoreW(hDlg, filelist.Buffer, dir.Buffer, 00844 basename.Buffer, dwFlags); 00845 00846 RtlFreeUnicodeString(&filelist); 00847 RtlFreeUnicodeString(&dir); 00848 RtlFreeUnicodeString(&basename); 00849 00850 return hr; 00851 } 00852 00853 /*********************************************************************** 00854 * FileSaveRestoreW (ADVPACK.@) 00855 * 00856 * Saves or restores the files in the specified file list. 00857 * 00858 * PARAMS 00859 * hDlg [I] Handle to the dialog used for the display. 00860 * pszFileList [I] NULL-separated list of filenames. 00861 * pszDir [I] Path of the backup directory. 00862 * pszBaseName [I] Basename of the backup files. 00863 * dwFlags [I] See advpub.h. 00864 * 00865 * RETURNS 00866 * Success: S_OK. 00867 * Failure: E_FAIL. 00868 * 00869 * NOTES 00870 * If pszFileList is NULL on restore, all files will be restored. 00871 * 00872 * BUGS 00873 * Unimplemented. 00874 */ 00875 HRESULT WINAPI FileSaveRestoreW(HWND hDlg, LPWSTR pszFileList, LPWSTR pszDir, 00876 LPWSTR pszBaseName, DWORD dwFlags) 00877 { 00878 FIXME("(%p, %s, %s, %s, %d) stub\n", hDlg, debugstr_w(pszFileList), 00879 debugstr_w(pszDir), debugstr_w(pszBaseName), dwFlags); 00880 00881 return E_FAIL; 00882 } 00883 00884 /*********************************************************************** 00885 * FileSaveRestoreOnINFA (ADVPACK.@) 00886 * 00887 * See FileSaveRestoreOnINFW. 00888 */ 00889 HRESULT WINAPI FileSaveRestoreOnINFA(HWND hWnd, LPCSTR pszTitle, LPCSTR pszINF, 00890 LPCSTR pszSection, LPCSTR pszBackupDir, 00891 LPCSTR pszBaseBackupFile, DWORD dwFlags) 00892 { 00893 UNICODE_STRING title, inf, section; 00894 UNICODE_STRING backupdir, backupfile; 00895 HRESULT hr; 00896 00897 TRACE("(%p, %s, %s, %s, %s, %s, %d)\n", hWnd, debugstr_a(pszTitle), 00898 debugstr_a(pszINF), debugstr_a(pszSection), debugstr_a(pszBackupDir), 00899 debugstr_a(pszBaseBackupFile), dwFlags); 00900 00901 RtlCreateUnicodeStringFromAsciiz(&title, pszTitle); 00902 RtlCreateUnicodeStringFromAsciiz(&inf, pszINF); 00903 RtlCreateUnicodeStringFromAsciiz(§ion, pszSection); 00904 RtlCreateUnicodeStringFromAsciiz(&backupdir, pszBackupDir); 00905 RtlCreateUnicodeStringFromAsciiz(&backupfile, pszBaseBackupFile); 00906 00907 hr = FileSaveRestoreOnINFW(hWnd, title.Buffer, inf.Buffer, section.Buffer, 00908 backupdir.Buffer, backupfile.Buffer, dwFlags); 00909 00910 RtlFreeUnicodeString(&title); 00911 RtlFreeUnicodeString(&inf); 00912 RtlFreeUnicodeString(§ion); 00913 RtlFreeUnicodeString(&backupdir); 00914 RtlFreeUnicodeString(&backupfile); 00915 00916 return hr; 00917 } 00918 00919 /*********************************************************************** 00920 * FileSaveRestoreOnINFW (ADVPACK.@) 00921 * 00922 * 00923 * PARAMS 00924 * hWnd [I] Handle to the window used for the display. 00925 * pszTitle [I] Title of the window. 00926 * pszINF [I] Fully-qualified INF filename. 00927 * pszSection [I] GenInstall INF section name. 00928 * pszBackupDir [I] Directory to store the backup file. 00929 * pszBaseBackupFile [I] Basename of the backup files. 00930 * dwFlags [I] See advpub.h 00931 * 00932 * RETURNS 00933 * Success: S_OK. 00934 * Failure: E_FAIL. 00935 * 00936 * NOTES 00937 * If pszSection is NULL, the default section will be used. 00938 * 00939 * BUGS 00940 * Unimplemented. 00941 */ 00942 HRESULT WINAPI FileSaveRestoreOnINFW(HWND hWnd, LPCWSTR pszTitle, LPCWSTR pszINF, 00943 LPCWSTR pszSection, LPCWSTR pszBackupDir, 00944 LPCWSTR pszBaseBackupFile, DWORD dwFlags) 00945 { 00946 FIXME("(%p, %s, %s, %s, %s, %s, %d): stub\n", hWnd, debugstr_w(pszTitle), 00947 debugstr_w(pszINF), debugstr_w(pszSection), debugstr_w(pszBackupDir), 00948 debugstr_w(pszBaseBackupFile), dwFlags); 00949 00950 return E_FAIL; 00951 } 00952 00953 /*********************************************************************** 00954 * GetVersionFromFileA (ADVPACK.@) 00955 * 00956 * See GetVersionFromFileExW. 00957 */ 00958 HRESULT WINAPI GetVersionFromFileA(LPCSTR Filename, LPDWORD MajorVer, 00959 LPDWORD MinorVer, BOOL Version ) 00960 { 00961 TRACE("(%s, %p, %p, %d)\n", debugstr_a(Filename), MajorVer, MinorVer, Version); 00962 return GetVersionFromFileExA(Filename, MajorVer, MinorVer, Version); 00963 } 00964 00965 /*********************************************************************** 00966 * GetVersionFromFileW (ADVPACK.@) 00967 * 00968 * See GetVersionFromFileExW. 00969 */ 00970 HRESULT WINAPI GetVersionFromFileW(LPCWSTR Filename, LPDWORD MajorVer, 00971 LPDWORD MinorVer, BOOL Version ) 00972 { 00973 TRACE("(%s, %p, %p, %d)\n", debugstr_w(Filename), MajorVer, MinorVer, Version); 00974 return GetVersionFromFileExW(Filename, MajorVer, MinorVer, Version); 00975 } 00976 00977 /* data for GetVersionFromFileEx */ 00978 typedef struct tagLANGANDCODEPAGE 00979 { 00980 WORD wLanguage; 00981 WORD wCodePage; 00982 } LANGANDCODEPAGE; 00983 00984 /*********************************************************************** 00985 * GetVersionFromFileExA (ADVPACK.@) 00986 * 00987 * See GetVersionFromFileExW. 00988 */ 00989 HRESULT WINAPI GetVersionFromFileExA(LPCSTR lpszFilename, LPDWORD pdwMSVer, 00990 LPDWORD pdwLSVer, BOOL bVersion ) 00991 { 00992 UNICODE_STRING filename; 00993 HRESULT res; 00994 00995 TRACE("(%s, %p, %p, %d)\n", debugstr_a(lpszFilename), 00996 pdwMSVer, pdwLSVer, bVersion); 00997 00998 RtlCreateUnicodeStringFromAsciiz(&filename, lpszFilename); 00999 01000 res = GetVersionFromFileExW(filename.Buffer, pdwMSVer, pdwLSVer, bVersion); 01001 01002 RtlFreeUnicodeString(&filename); 01003 01004 return res; 01005 } 01006 01007 /*********************************************************************** 01008 * GetVersionFromFileExW (ADVPACK.@) 01009 * 01010 * Gets the files version or language information. 01011 * 01012 * PARAMS 01013 * lpszFilename [I] The file to get the info from. 01014 * pdwMSVer [O] Major version. 01015 * pdwLSVer [O] Minor version. 01016 * bVersion [I] Whether to retrieve version or language info. 01017 * 01018 * RETURNS 01019 * Always returns S_OK. 01020 * 01021 * NOTES 01022 * If bVersion is TRUE, version information is retrieved, else 01023 * pdwMSVer gets the language ID and pdwLSVer gets the codepage ID. 01024 */ 01025 HRESULT WINAPI GetVersionFromFileExW(LPCWSTR lpszFilename, LPDWORD pdwMSVer, 01026 LPDWORD pdwLSVer, BOOL bVersion ) 01027 { 01028 VS_FIXEDFILEINFO *pFixedVersionInfo; 01029 LANGANDCODEPAGE *pLangAndCodePage; 01030 DWORD dwHandle, dwInfoSize; 01031 WCHAR szWinDir[MAX_PATH]; 01032 WCHAR szFile[MAX_PATH]; 01033 LPVOID pVersionInfo = NULL; 01034 BOOL bFileCopied = FALSE; 01035 UINT uValueLen; 01036 01037 static const WCHAR backslash[] = {'\\',0}; 01038 static const WCHAR translation[] = { 01039 '\\','V','a','r','F','i','l','e','I','n','f','o', 01040 '\\','T','r','a','n','s','l','a','t','i','o','n',0 01041 }; 01042 01043 TRACE("(%s, %p, %p, %d)\n", debugstr_w(lpszFilename), 01044 pdwMSVer, pdwLSVer, bVersion); 01045 01046 *pdwLSVer = 0; 01047 *pdwMSVer = 0; 01048 01049 lstrcpynW(szFile, lpszFilename, MAX_PATH); 01050 01051 dwInfoSize = GetFileVersionInfoSizeW(szFile, &dwHandle); 01052 if (!dwInfoSize) 01053 { 01054 /* check that the file exists */ 01055 if (GetFileAttributesW(szFile) == INVALID_FILE_ATTRIBUTES) 01056 return S_OK; 01057 01058 /* file exists, but won't be found by GetFileVersionInfoSize, 01059 * so copy it to the temp dir where it will be found. 01060 */ 01061 GetWindowsDirectoryW(szWinDir, MAX_PATH); 01062 GetTempFileNameW(szWinDir, NULL, 0, szFile); 01063 CopyFileW(lpszFilename, szFile, FALSE); 01064 bFileCopied = TRUE; 01065 01066 dwInfoSize = GetFileVersionInfoSizeW(szFile, &dwHandle); 01067 if (!dwInfoSize) 01068 goto done; 01069 } 01070 01071 pVersionInfo = HeapAlloc(GetProcessHeap(), 0, dwInfoSize); 01072 if (!pVersionInfo) 01073 goto done; 01074 01075 if (!GetFileVersionInfoW(szFile, dwHandle, dwInfoSize, pVersionInfo)) 01076 goto done; 01077 01078 if (bVersion) 01079 { 01080 if (!VerQueryValueW(pVersionInfo, backslash, 01081 (LPVOID *)&pFixedVersionInfo, &uValueLen)) 01082 goto done; 01083 01084 if (!uValueLen) 01085 goto done; 01086 01087 *pdwMSVer = pFixedVersionInfo->dwFileVersionMS; 01088 *pdwLSVer = pFixedVersionInfo->dwFileVersionLS; 01089 } 01090 else 01091 { 01092 if (!VerQueryValueW(pVersionInfo, translation, 01093 (LPVOID *)&pLangAndCodePage, &uValueLen)) 01094 goto done; 01095 01096 if (!uValueLen) 01097 goto done; 01098 01099 *pdwMSVer = pLangAndCodePage->wLanguage; 01100 *pdwLSVer = pLangAndCodePage->wCodePage; 01101 } 01102 01103 done: 01104 HeapFree(GetProcessHeap(), 0, pVersionInfo); 01105 01106 if (bFileCopied) 01107 DeleteFileW(szFile); 01108 01109 return S_OK; 01110 } Generated on Fri May 25 2012 04:20:46 for ReactOS by
1.7.6.1
|