Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

284 lines
9.3 KiB

  1. #include <windows.h>
  2. #include <winerror.h>
  3. #include <ole2.h>
  4. #include "cpldebug.h"
  5. #include "cab_dll.h"
  6. //typedef HRESULT (WINAPI *EXTRACT) (PSESSION psess, LPCSTR lpCabName);
  7. VOID FreeFileList(PSESSION psess);
  8. VOID FreeFileNode(PFNAME pfname);
  9. BOOL IsFileInList(LPSTR pszFile, LPSTR pszFileList);
  10. int PrepareFileList(LPSTR pszOutFileList, LPCSTR pszInFileList);
  11. // BUGBUG: Minimum version of Cabinet DLL that supports the new Extract API
  12. // the one that was formerly in URLMON.DLL.
  13. //
  14. #define MIN_CABINETDLL_MSVER 0
  15. #define MIN_CABINETDLL_LSVER 0
  16. //=--------------------------------------------------------------------------=
  17. // ExtractFiles
  18. //=--------------------------------------------------------------------------=
  19. //
  20. // Parameters:
  21. // LPCSTR pszCabName - [in] full qualified filename to the .CAB file
  22. // LPCSTR pszExpandDir- [in] full qualified path to where to extract the file(s)
  23. // DWORD dwFlags - [in] Flags, currently not used
  24. // LPCSTR pszFileList - [in] colon separated list of files to extract from pszCabName
  25. // or NULL for all files
  26. // LPVOID lpReserved - [in] currently not used
  27. // DWORD dwReserved - [in] currently not used
  28. //
  29. // Return HRESULT:
  30. // E_INVALIDARG - if pszCabName or pszExpandDir == NULL
  31. // E_OUTOFMEMORY - if we could not allocate our memory
  32. // E_FAIL - if no files in pszFileList and pszFileList!=NULL
  33. // if not all files from pszFileList are in the .CAB file
  34. // if Extract return S_FALSE
  35. // any E_ code Extract returns
  36. //
  37. // Note: This function would not extract any file from the pszFileList, if not all
  38. // of them are in the .CAB file. If one or more are not in the .CAB file
  39. // the function does not extract any and returns E_FAIL
  40. //
  41. HRESULT WINAPI ExtractFiles( LPCSTR pszCabName, LPCSTR pszExpandDir, DWORD dwFlags,
  42. LPCSTR pszFileList, LPVOID lpReserved, DWORD dwReserved)
  43. {
  44. HINSTANCE hinst;
  45. PSESSION psess = NULL;
  46. PFNAME pf = NULL;
  47. PFNAME pfPriv = NULL;
  48. HRESULT hr = E_FAIL; // Return error
  49. LPSTR pszMyFileList = NULL;
  50. PFN_EXTRACT fpExtract = NULL;
  51. PFN_DLLGETVERSION fpGetVer = NULL;
  52. int iFiles = 0; // number of files in list
  53. CABINETDLLVERSIONINFO cabDllVer;
  54. // Do checking for valid values??
  55. if ((!pszCabName) || (!pszExpandDir))
  56. return E_INVALIDARG;
  57. hinst = LoadLibrary("CABINET.DLL");
  58. if (hinst)
  59. {
  60. fpGetVer = (PFN_DLLGETVERSION)GetProcAddress(hinst, "DllGetVersion");
  61. // Make sure this is the CABINET.DLL that supports the Extract API
  62. //
  63. if ( fpGetVer )
  64. {
  65. cabDllVer.cbStruct = sizeof(cabDllVer);
  66. fpGetVer( &cabDllVer );
  67. if ( (cabDllVer.dwFileVersionMS > MIN_CABINETDLL_MSVER) ||
  68. (cabDllVer.dwFileVersionMS == MIN_CABINETDLL_MSVER) /* && (cabDllVer.dwFileVersionLS >= MIN_CABINETDLL_LSVER) */ )
  69. {
  70. fpExtract = (PFN_EXTRACT)GetProcAddress(hinst, "Extract");
  71. }
  72. }
  73. if (!fpExtract)
  74. FreeLibrary(hinst);
  75. }
  76. // If we did not get the Extract() API from cabinet.dll go for
  77. // URLMON.DLL
  78. //
  79. if (!fpExtract)
  80. {
  81. hinst = LoadLibrary("URLMON.DLL");
  82. if (hinst)
  83. fpExtract = (PFN_EXTRACT)GetProcAddress(hinst, "Extract");
  84. }
  85. if (fpExtract)
  86. {
  87. psess = (PSESSION)LocalAlloc(LPTR, sizeof(SESSION));
  88. if (psess)
  89. {
  90. lstrcpy(psess->achLocation, pszExpandDir);
  91. // Initialize the structure
  92. if (pszFileList == NULL)
  93. {
  94. // Extract all
  95. psess->flags = SESSION_FLAG_EXTRACT_ALL|SESSION_FLAG_ENUMERATE;
  96. hr = fpExtract(psess, pszCabName);
  97. // BUGBUG: What if psess->erf reports an error??
  98. }
  99. else
  100. {
  101. // I append a '/0' therefor +2
  102. pszMyFileList = (LPSTR)LocalAlloc(LPTR, lstrlen(pszFileList)+2);
  103. if (pszMyFileList)
  104. {
  105. iFiles = PrepareFileList(pszMyFileList, pszFileList);
  106. psess->flags = SESSION_FLAG_ENUMERATE;
  107. if ((iFiles > 0) &&
  108. ( !FAILED(hr = fpExtract(psess, pszCabName)) ))
  109. // What if psess->erf reports an error??
  110. {
  111. // If there are files in the list and we enumarated files
  112. // Got the list of files in the cab
  113. pfPriv = NULL;
  114. pf = psess->pFileList;
  115. while (pf != NULL )
  116. {
  117. if (!IsFileInList(pf->pszFilename, pszMyFileList))
  118. {
  119. // Delete the node from the list
  120. if (pfPriv == NULL)
  121. {
  122. // Delete the head
  123. psess->pFileList = pf->pNextName;
  124. FreeFileNode(pf);
  125. pf = psess->pFileList;
  126. }
  127. else
  128. {
  129. pfPriv->pNextName = pf->pNextName;
  130. FreeFileNode(pf);
  131. pf = pfPriv->pNextName;
  132. }
  133. }
  134. else
  135. {
  136. // Just go to the next one
  137. pfPriv = pf;
  138. pf = pf->pNextName;
  139. iFiles--;
  140. }
  141. }
  142. if ((psess->pFileList) && (iFiles == 0))
  143. {
  144. // Reset the error flag
  145. psess->erf.fError = FALSE;
  146. psess->erf.erfOper = 0;
  147. psess->pFilesToExtract = psess->pFileList;
  148. psess->flags &= ~SESSION_FLAG_ENUMERATE; // already enumerated
  149. hr = fpExtract(psess, pszCabName);
  150. // BUGBUG: What if psess->erf reports an error??
  151. }
  152. else
  153. hr = E_FAIL; // File(s) is not in cab.
  154. }
  155. LocalFree(pszMyFileList);
  156. pszMyFileList = NULL;
  157. }
  158. else
  159. hr = E_OUTOFMEMORY;
  160. }
  161. FreeFileList(psess);
  162. LocalFree(psess);
  163. psess = NULL;
  164. }
  165. else
  166. hr = E_OUTOFMEMORY;
  167. }
  168. if (hinst)
  169. FreeLibrary(hinst);
  170. // Extract may only return S_FALSE in a failure case.
  171. if (!FAILED(hr) && (hr == S_FALSE))
  172. hr = E_FAIL;
  173. return (hr);
  174. }
  175. VOID FreeFileList(PSESSION psess)
  176. {
  177. PFNAME rover = psess->pFileList;
  178. PFNAME roverprev;
  179. while (rover != NULL)
  180. {
  181. roverprev = rover; // save for free'ing current rover below
  182. rover = rover->pNextName;
  183. FreeFileNode(roverprev);
  184. }
  185. psess->pFileList = NULL; // prevent use after deletion!
  186. }
  187. VOID FreeFileNode(PFNAME pfname)
  188. {
  189. CoTaskMemFree(pfname->pszFilename);
  190. CoTaskMemFree(pfname);
  191. }
  192. BOOL IsFileInList(LPSTR pszFile, LPSTR pszFileList)
  193. {
  194. char *p;
  195. int iLenFile = lstrlen(pszFile);
  196. BOOL bFound = FALSE;
  197. p = pszFileList;
  198. while ((*p != '\0') && (!bFound))
  199. {
  200. if (lstrlen(p) == iLenFile)
  201. bFound = (lstrcmpi(p, pszFile) == 0);
  202. if (!bFound)
  203. p += lstrlen(p) + 1;
  204. }
  205. return (bFound);
  206. }
  207. int PrepareFileList(LPSTR pszOutFileList, LPCSTR pszInFileList)
  208. {
  209. int iFiles = 0; // number of files in list
  210. char *p;
  211. p = (LPSTR)pszInFileList; // p is used to point into both arrays
  212. // trim leading spaces, tabs or :
  213. while ((*p == ' ') || (*p == '\t') || (*p == ':'))
  214. p++;
  215. lstrcpy(pszOutFileList, p);
  216. p = pszOutFileList;
  217. if (lstrlen(pszOutFileList) > 0)
  218. {
  219. // Only if we have atleast one character left.
  220. // This cannot be a space of tab, because we
  221. // would have removed this above.
  222. p += (lstrlen(pszOutFileList) - 1);
  223. // trim railing spaces, tabs or :
  224. while ((*p == ' ') || (*p == '\t') || (*p == ':'))
  225. p--;
  226. // Put a '\0' for the last space/tab
  227. *(++p) = '\0';
  228. }
  229. if (*pszOutFileList)
  230. {
  231. iFiles++;
  232. // Now replace ':' with '\0'
  233. p = pszOutFileList;
  234. while (*p != '\0')
  235. {
  236. if (*p == ':')
  237. {
  238. *p = '\0';
  239. iFiles++;
  240. }
  241. p++;
  242. }
  243. // Make sure we have a double '\0' at the end.
  244. *(++p) = '\0';
  245. }
  246. return iFiles;
  247. }