Source code of Windows XP (NT5)
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.

436 lines
8.0 KiB

  1. /*++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name:
  4. ntcab.c
  5. Abstract:
  6. NTCab compression support.
  7. Author:
  8. Ted Miller (tedm) 31-Jan-1995
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. BOOL
  14. NtCabNotifyFunction(
  15. IN PNTCAB_ENUM_DATA EnumData,
  16. IN PVOID Cntxt
  17. )
  18. {
  19. PNTCABCONTEXT Context = Cntxt;
  20. BOOL rc;
  21. DWORD Operation;
  22. PSTR FileNameA;
  23. CABINET_INFO CabInfo;
  24. FILE_IN_CABINET_INFO FileInCab;
  25. FILETIME FileTime, UtcTime;
  26. TCHAR NewPath[MAX_PATH];
  27. PTSTR p;
  28. rc = ((PSP_NTCAB_CALLBACK)Context->MsgHandler)( EnumData, Context, &Operation );
  29. if (rc == ERROR_REQUEST_ABORTED) {
  30. //
  31. // this means stop making callback
  32. //
  33. return(FALSE);
  34. }
  35. #if 0
  36. switch(Operation) {
  37. case FILEOP_SKIP:
  38. //
  39. // do nothing
  40. //
  41. ;
  42. break;
  43. case FILEOP_DOIT:
  44. ;
  45. break;
  46. default:
  47. //
  48. // Abort.
  49. //
  50. return(FALSE);
  51. break;
  52. }
  53. #endif
  54. return(TRUE);
  55. }
  56. #ifdef UNICODE
  57. DWORD
  58. NtCabProcessCabinet(
  59. //IN PVOID InCabHandle, OPTIONAL
  60. IN PCTSTR CabinetFile,
  61. IN DWORD Flags,
  62. IN PVOID MsgHandler,
  63. IN PVOID Context,
  64. IN BOOL IsMsgHandlerNativeCharWidth
  65. )
  66. /*++
  67. Routine Description:
  68. Process an ntcab file, iterating through all files
  69. contained within it and calling the callback function with
  70. information about each file.
  71. Arguments:
  72. CabHandle - supplies a handle to the cab file, if it already exists,
  73. otherwise, a new handle is created
  74. CabinetFile - supplies name of cabinet file.
  75. Flags - supplies flags to control behavior of cabinet processing.
  76. MsgHandler - Supplies a callback routine to be notified
  77. of various significant events in cabinet processing.
  78. Context - Supplies a value that is passed to the MsgHandler
  79. callback function.
  80. Return Value:
  81. Win32 error code indicating result. If the cabinet was corrupt,
  82. ERROR_INVALID_DATA is returned.
  83. --*/
  84. {
  85. BOOL b;
  86. DWORD rc;
  87. PWSTR CabCopy, FilePart,PathPart,tmp;
  88. WCHAR c;
  89. WCHAR fullcab[MAX_PATH];
  90. int h;
  91. PVOID CabHandle;
  92. NTCABCONTEXT CabContext;
  93. UNREFERENCED_PARAMETER(Flags);
  94. //
  95. // Initialize diamond for this thread if not
  96. // already initialized.
  97. //
  98. //if(!InCabHandle) {
  99. CabHandle = NtCabInitialize();
  100. if (!CabHandle) {
  101. rc = ERROR_INVALID_HANDLE;
  102. goto c0;
  103. }
  104. //} else {
  105. // CabHandle = InCabHandle;
  106. //}
  107. if (!CabinetFile) {
  108. rc = ERROR_INVALID_PARAMETER;
  109. goto c1;
  110. }
  111. MYASSERT( CabHandle != NULL );
  112. MYASSERT( CabinetFile != NULL );
  113. //
  114. // make a copy because the input is const
  115. //
  116. CabCopy = DuplicateString(CabinetFile);
  117. if (!CabCopy) {
  118. rc = ERROR_NOT_ENOUGH_MEMORY;
  119. goto c1;
  120. }
  121. //
  122. // Split the cabinet name into path and name.
  123. // Make separate copies because we want to remember the
  124. //
  125. if(FilePart = wcsrchr(CabCopy, L'\\')) {
  126. FilePart++;
  127. } else {
  128. FilePart = CabCopy;
  129. }
  130. c = *FilePart;
  131. *FilePart = 0;
  132. PathPart = DuplicateString(CabCopy);
  133. *FilePart = c;
  134. if(!PathPart) {
  135. rc = ERROR_NOT_ENOUGH_MEMORY;
  136. goto c2;
  137. }
  138. FilePart = DuplicateString(FilePart);
  139. if(!FilePart) {
  140. rc = ERROR_NOT_ENOUGH_MEMORY;
  141. goto c3;
  142. }
  143. MyFree( CabCopy );
  144. MYASSERT( FilePart != NULL && PathPart != NULL );
  145. rc = GetFullPathName(CabinetFile,MAX_PATH,fullcab,&tmp);
  146. if (!rc || rc > MAX_PATH) {
  147. rc = ERROR_BUFFER_OVERFLOW;
  148. goto c4;
  149. } else if (GetFileAttributes(fullcab) == 0xFFFFFFFF) {
  150. rc = ERROR_FILE_NOT_FOUND;
  151. goto c4;
  152. }
  153. if (!NtCabOpenCabFile(CabHandle,fullcab)) {
  154. rc = ERROR_INVALID_DATA;
  155. goto c4;
  156. }
  157. CabContext.hCab = CabHandle;
  158. CabContext.UserContext = Context;
  159. CabContext.CabFile = CabinetFile;
  160. CabContext.FilePart = FilePart;
  161. CabContext.PathPart = PathPart;
  162. CabContext.IsMsgHandlerNativeCharWidth = IsMsgHandlerNativeCharWidth;
  163. CabContext.MsgHandler = MsgHandler;
  164. CabContext.LastError = ERROR_SUCCESS;
  165. CabContext.CurrentTargetFile = NULL;
  166. //CabContext.UserPath[0] = 0;
  167. //CabContext.SwitchedCabinets = FALSE ;
  168. //
  169. // call cab enumeration callback
  170. //
  171. b = NtCabEnumerateFiles(
  172. CabHandle,
  173. (PNTCABFILEENUM)NtCabNotifyFunction,
  174. (ULONG_PTR)&CabContext);
  175. if(b && GetLastError()==ERROR_NO_MORE_FILES) {
  176. //
  177. // Everything succeeded so we shouldn't have any partially
  178. // processed files.
  179. //
  180. SetLastError(NO_ERROR);
  181. MYASSERT(!CabContext.CurrentTargetFile);
  182. rc = NO_ERROR;
  183. } else {
  184. rc = CabContext.LastError;
  185. #if 0
  186. switch(CabContext.LastError) {
  187. case :
  188. break;
  189. default:
  190. //
  191. // Cabinet is corrupt or not actually a cabinet, etc.
  192. //
  193. rc = ERROR_INVALID_DATA;
  194. break;
  195. }
  196. #endif
  197. if(CabContext.CurrentTargetFile) {
  198. //
  199. // Call the callback function to inform it that the last file
  200. // was not successfully extracted from the cabinet.
  201. // Also remove the partially copied file.
  202. //
  203. DeleteFile(CabContext.CurrentTargetFile);
  204. CabContext.CurrentTargetFile = NULL;
  205. }
  206. }
  207. c4:
  208. MyFree(FilePart);
  209. c3:
  210. MyFree(PathPart);
  211. c2:
  212. MyFree(CabCopy);
  213. c1:
  214. //if (CabHandle != InCabHandle) {
  215. NtCabClose( CabHandle );
  216. //}
  217. c0:
  218. return(rc);
  219. }
  220. #else
  221. DWORD
  222. NtCabProcessCabinet(
  223. //IN PVOID InCabHandle, OPTIONAL
  224. IN PCTSTR CabinetFile,
  225. IN DWORD Flags,
  226. IN PVOID MsgHandler,
  227. IN PVOID Context,
  228. IN BOOL IsMsgHandlerNativeCharWidth
  229. )
  230. {
  231. //UNREFERENCED_PARAMETER(InCabHandle);
  232. UNREFERENCED_PARAMETER(CabinetFile);
  233. UNREFERENCED_PARAMETER(Flags);
  234. UNREFERENCED_PARAMETER(MsgHandler);
  235. UNREFERENCED_PARAMETER(Context);
  236. UNREFERENCED_PARAMETER(IsMsgHandlerNativeCharWidth);
  237. return(ERROR_CALL_NOT_IMPLEMENTED);
  238. }
  239. #endif
  240. #ifdef UNICODE
  241. BOOL
  242. NtCabIsCabinet(
  243. IN PCWSTR CabinetFile
  244. )
  245. /*++
  246. Routine Description:
  247. Determine if a file is a diamond cabinet.
  248. Arguments:
  249. FileName - supplies name of file to be checked.
  250. Return Value:
  251. TRUE if file is diamond file. FALSE if not;
  252. --*/
  253. {
  254. DWORD rc;
  255. PVOID CabHandle;
  256. WCHAR fullcab[MAX_PATH];
  257. PWSTR tmp;
  258. CabHandle = NtCabInitialize();
  259. if (!CabHandle) {
  260. rc = ERROR_INVALID_DATA;
  261. goto c0;
  262. }
  263. rc = GetFullPathName(CabinetFile,MAX_PATH,fullcab,&tmp);
  264. if (!rc || rc > MAX_PATH) {
  265. rc = ERROR_BUFFER_OVERFLOW;
  266. goto c1;
  267. } else if (GetFileAttributes(fullcab) == 0xFFFFFFFF) {
  268. rc = ERROR_FILE_NOT_FOUND;
  269. goto c1;
  270. }
  271. if (!NtCabOpenCabFile(CabHandle,fullcab)) {
  272. rc = ERROR_INVALID_DATA;
  273. goto c1;
  274. }
  275. rc = ERROR_SUCCESS;
  276. c1:
  277. NtCabClose(CabHandle);
  278. c0:
  279. return(rc == ERROR_SUCCESS);
  280. }
  281. #else
  282. BOOL
  283. NtCabIsCabinet(
  284. IN PCWSTR FileName
  285. )
  286. {
  287. UNREFERENCED_PARAMETER(FileName);
  288. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  289. return(FALSE);
  290. }
  291. #endif
  292. PVOID
  293. NtCabAlloc(
  294. IN ULONG NumberOfBytes
  295. )
  296. /*++
  297. Routine Description:
  298. Callback used by cab callback to allocate memory.
  299. Arguments:
  300. NumberOfBytes - supplies desired size of block.
  301. Return Value:
  302. Returns pointer to a block of memory or NULL
  303. if memory cannot be allocated.
  304. --*/
  305. {
  306. return(MyMalloc(NumberOfBytes));
  307. }
  308. VOID
  309. NtCabFree(
  310. IN PVOID Block
  311. )
  312. /*++
  313. Routine Description:
  314. Callback used by cab callback to free a memory block.
  315. The block must have been allocated with NtCabAlloc().
  316. Arguments:
  317. Block - supplies pointer to block of memory to be freed.
  318. Return Value:
  319. None.
  320. --*/
  321. {
  322. MyFree(Block);
  323. }