ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

files.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(&params, cmdline);
00467 
00468     hr = DelNodeRunDLL32W(hWnd, hInst, params.Buffer, show);
00469 
00470     RtlFreeUnicodeString(&params);
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(&section, 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(&section);
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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.