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.

552 lines
17 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // File: cmfdi.cpp
  4. //
  5. // Module: CMDL32.EXE
  6. //
  7. // Synopsis: CFdi class implementations
  8. //
  9. // Copyright (c) 1996-1999 Microsoft Corporation
  10. //
  11. // Author: nickball Created 04/08/98
  12. //
  13. //+----------------------------------------------------------------------------
  14. #include "cmmaster.h"
  15. #include <fcntl.h>
  16. #include <sys\stat.h>
  17. const TCHAR* const c_pszExeFile = TEXT("PBUPDATE.EXE"); // for detecting itExeInCab
  18. const TCHAR* const c_pszInfFile = TEXT("PBUPDATE.INF"); // for detecting itInfInCab
  19. const TCHAR* const c_pszVerFile = TEXT("PBUPDATE.VER"); // version string in .CAB
  20. const TCHAR* const c_pszPbr = TEXT("PBR"); // regions file extension
  21. //
  22. // CFDIFile Implementation
  23. //
  24. CFDIFile::~CFDIFile()
  25. {
  26. // nothing
  27. }
  28. DWORD CFDIFile::Read(LPVOID pv, DWORD cb)
  29. {
  30. return 0;
  31. }
  32. DWORD CFDIFile::Write(LPVOID pv, DWORD cb)
  33. {
  34. return 0;
  35. }
  36. long CFDIFile::Seek(long dist, int seektype)
  37. {
  38. return 0;
  39. }
  40. int CFDIFile::Close()
  41. {
  42. return 0;
  43. }
  44. HANDLE CFDIFile::GetHandle()
  45. {
  46. return (INVALID_HANDLE_VALUE);
  47. }
  48. //
  49. // CFDIFileFile Implementation
  50. //
  51. CFDIFileFile::CFDIFileFile()
  52. {
  53. m_hFile = INVALID_HANDLE_VALUE;
  54. }
  55. CFDIFileFile::~CFDIFileFile()
  56. {
  57. if (m_hFile != INVALID_HANDLE_VALUE) {
  58. MYDBG(("CFDIFileFile::~CFDIFileFile() destructor called while file still open."));
  59. Close();
  60. }
  61. }
  62. BOOL CFDIFileFile::CreateFile(LPCTSTR pszFile,
  63. DWORD dwDesiredAccess,
  64. DWORD dwShareMode,
  65. DWORD dwCreationDistribution,
  66. DWORD dwFlagsAndAttributes,
  67. DWORD dwFileSize)
  68. {
  69. // Make sure the files isn't in use
  70. if (m_hFile != INVALID_HANDLE_VALUE)
  71. {
  72. MYDBG(("CFDIFileFile::CreateFile() file is already open."));
  73. SetLastError(ERROR_OUT_OF_STRUCTURES);
  74. return (FALSE);
  75. }
  76. // Open Create/Open the file
  77. m_hFile = ::CreateFile(pszFile,dwDesiredAccess,dwShareMode,NULL,dwCreationDistribution,dwFlagsAndAttributes,NULL);
  78. if (m_hFile == INVALID_HANDLE_VALUE)
  79. {
  80. MYDBG(("CFDIFileFile::CreateFile() CreateFile(pszFile=%s,dwDesiredAccess=%u,dwShareMode=%u,dwCreationDistribution=%u,dwFlagsAndAttributes=%u) failed, GLE=%u.",
  81. pszFile,dwDesiredAccess,dwShareMode,dwCreationDistribution,dwFlagsAndAttributes,GetLastError()));
  82. return (FALSE);
  83. }
  84. // If dwFileSize is specified, move the pointer by dwFileSize bytes
  85. if (dwFileSize)
  86. {
  87. BOOL bRes;
  88. DWORD dwRes;
  89. dwRes = SetFilePointer(m_hFile,dwFileSize,NULL,FILE_BEGIN);
  90. MYDBGTST(dwRes==INVALID_SET_FILE_POINTER ,("CFDIFileFile::CreateFile() SetFilePointer() failed, GLE=%u.",GetLastError()));
  91. // If that worked, set the end of file at the file pointer position
  92. if (dwRes != INVALID_SET_FILE_POINTER)
  93. {
  94. bRes = SetEndOfFile(m_hFile);
  95. MYDBGTST(!bRes,("CFDIFileFile::CreateFile() SetEndOfFile() failed, GLE=%u.",GetLastError()));
  96. }
  97. // Reset the file pointer to the beginning
  98. if ((dwRes != INVALID_SET_FILE_POINTER ) && bRes)
  99. {
  100. dwRes = SetFilePointer(m_hFile,0,NULL,FILE_BEGIN);
  101. MYDBGTST(dwRes==INVALID_SET_FILE_POINTER ,("CFDIFileFile::CreateFile() SetFilePointer() failed, GLE=%u.",GetLastError()));
  102. }
  103. // Close the file and bail if we failed the above
  104. if ((dwRes == INVALID_SET_FILE_POINTER ) || !bRes)
  105. {
  106. bRes = CloseHandle(m_hFile);
  107. MYDBGTST(!bRes,("CFDIFileFile::CreateFile() CloseHandle() failed, GLE=%u.",GetLastError()));
  108. m_hFile = INVALID_HANDLE_VALUE;
  109. return (-1);
  110. }
  111. }
  112. return (TRUE);
  113. }
  114. BOOL CFDIFileFile::CreateUniqueFile(LPTSTR pszFile, DWORD dwDesiredAccess, DWORD dwShareMode, DWORD dwFlagsAndAttributes)
  115. {
  116. DWORD dwIdx;
  117. TCHAR szFile[MAX_PATH+1];
  118. if (m_hFile != INVALID_HANDLE_VALUE) {
  119. MYDBG(("CFDIFileFile::CreateUniqueFile() file is already open."));
  120. SetLastError(ERROR_OUT_OF_STRUCTURES);
  121. return (FALSE);
  122. }
  123. dwIdx = 0;
  124. while (1) {
  125. wsprintf(szFile,"%08u.tmp",dwIdx);
  126. m_hFile = ::CreateFile(szFile,dwDesiredAccess,dwShareMode,NULL,CREATE_NEW,dwFlagsAndAttributes,NULL);
  127. if (m_hFile != INVALID_HANDLE_VALUE) {
  128. break;
  129. }
  130. if (IsErrorForUnique(GetLastError(), szFile)) {
  131. MYDBG(("CFDIFileFile::CreateUniqueFile() CreateFile() failed, GLE=%u.",GetLastError()));
  132. return (FALSE);
  133. }
  134. dwIdx++;
  135. }
  136. lstrcpy(pszFile,szFile);
  137. return (TRUE);
  138. }
  139. DWORD CFDIFileFile::Read(LPVOID pv, DWORD cb)
  140. {
  141. BOOL bRes;
  142. DWORD dwRes;
  143. bRes = ReadFile(m_hFile,pv,cb,&dwRes,NULL);
  144. if (!bRes) {
  145. MYDBG(("CFDIFileFile::Read() ReadFile() failed, GLE=%u.",GetLastError()));
  146. return ((UINT) -1);
  147. }
  148. return (dwRes);
  149. }
  150. DWORD CFDIFileFile::Write(LPVOID pv, DWORD cb)
  151. {
  152. BOOL bRes;
  153. DWORD dwRes;
  154. bRes = WriteFile(m_hFile,pv,cb,&dwRes,NULL);
  155. if (!bRes) {
  156. MYDBG(("CFDIFileFile::Write() WriteFile() failed, GLE=%u.",GetLastError()));
  157. return ((UINT) -1);
  158. }
  159. return (dwRes);
  160. }
  161. long CFDIFileFile::Seek(long dist, int seektype)
  162. {
  163. DWORD dwRes;
  164. dwRes = SetFilePointer(m_hFile,dist,NULL,seektype);
  165. if (dwRes == INVALID_SET_FILE_POINTER) {
  166. MYDBG(("CFDIFileFile::Seek() SetFilePointer() failed, GLE=%u.",GetLastError()));
  167. return (-1);
  168. }
  169. return ((long) dwRes);
  170. }
  171. int CFDIFileFile::Close()
  172. {
  173. BOOL bRes;
  174. bRes = CloseHandle(m_hFile);
  175. if (!bRes) {
  176. MYDBG(("CFDIFileFile::Close() CloseHandle() failed, GLE=%u.",GetLastError()));
  177. return (-1);
  178. }
  179. m_hFile = INVALID_HANDLE_VALUE;
  180. return (0);
  181. }
  182. HANDLE CFDIFileFile::GetHandle()
  183. {
  184. return (m_hFile);
  185. }
  186. //
  187. // FDI wrapper routines
  188. //
  189. void HUGE * FAR DIAMONDAPI fdi_alloc(ULONG cb)
  190. {
  191. return (CmMalloc(cb));
  192. }
  193. void FAR DIAMONDAPI fdi_free(void HUGE *pv)
  194. {
  195. CmFree(pv);
  196. }
  197. INT_PTR FAR DIAMONDAPI fdi_open(char FAR *pszFile, int oflag, int pmode)
  198. {
  199. TCHAR szTempFileName[MAX_PATH+1];
  200. DWORD dwDesiredAccess;
  201. DWORD dwShareMode = FILE_SHARE_READ;
  202. DWORD dwCreationDistribution;
  203. DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
  204. DWORD dwFileSize = 0;
  205. DWORD dwRes;
  206. BOOL bRes;
  207. CFDIFileFile *pfff = NULL;
  208. pfff = new CFDIFileFile;
  209. if (!pfff) {
  210. MYDBG(("fdi_open() new CFDIFileFile failed."));
  211. return (-1);
  212. }
  213. switch (oflag & (_O_RDONLY|_O_WRONLY|_O_RDWR)) {
  214. case _O_RDONLY:
  215. dwDesiredAccess = GENERIC_READ;
  216. break;
  217. case _O_WRONLY:
  218. dwDesiredAccess = GENERIC_WRITE;
  219. break;
  220. case _O_RDWR:
  221. dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
  222. break;
  223. default:
  224. MYDBG(("fdi_open() invalid read/write flags, oflag=%u.",oflag));
  225. delete pfff;
  226. return (-1);
  227. }
  228. if (oflag & _O_CREAT) {
  229. if (!(pmode & _S_IWRITE)) {
  230. dwFlagsAndAttributes |= FILE_ATTRIBUTE_READONLY;
  231. }
  232. }
  233. if (oflag & (_O_CREAT | _O_EXCL)) {
  234. dwCreationDistribution = CREATE_NEW;
  235. } else if (oflag & (_O_CREAT | _O_TRUNC)) {
  236. dwCreationDistribution = CREATE_ALWAYS;
  237. } else if (oflag & _O_CREAT) {
  238. dwCreationDistribution = OPEN_ALWAYS;
  239. } else if (oflag & _O_TRUNC) {
  240. dwCreationDistribution = TRUNCATE_EXISTING;
  241. } else {
  242. dwCreationDistribution = OPEN_EXISTING;
  243. }
  244. if (*pszFile == '*') {
  245. PFDISPILLFILE pfsf = (PFDISPILLFILE) pszFile;
  246. TCHAR szTempPath[MAX_PATH+1];
  247. ZeroMemory(szTempPath,sizeof(szTempPath));
  248. ZeroMemory(szTempFileName,sizeof(szTempFileName));
  249. dwRes = GetTempPath(sizeof(szTempPath)/sizeof(TCHAR)-1,szTempPath);
  250. MYDBGTST(!dwRes,("fdi_open() GetTempPath() failed, GLE=%u.",GetLastError()));
  251. dwRes = GetTempFileName(szTempPath,TEXT("ctf"),0,szTempFileName);
  252. MYDBGTST(!dwRes,("fdi_open() GetTempFileName() failed, GLE=%u.",GetLastError()));
  253. MYDBGTST(!dwRes,("fdi_open() GetTempFileName() failed, GLE=%u.",GetLastError()));
  254. pszFile = szTempFileName;
  255. dwFileSize = pfsf->cbFile;
  256. dwFlagsAndAttributes |= FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE;
  257. }
  258. bRes = pfff->CreateFile(pszFile,dwDesiredAccess,dwShareMode,dwCreationDistribution,dwFlagsAndAttributes,dwFileSize);
  259. if (!bRes) {
  260. delete pfff;
  261. return (-1);
  262. }
  263. return ((INT_PTR)pfff);
  264. }
  265. UINT FAR DIAMONDAPI fdi_read(INT_PTR hf, void FAR *pv, UINT cb)
  266. {
  267. return (((CFDIFile *) hf)->Read(pv,cb));
  268. }
  269. UINT FAR DIAMONDAPI fdi_write(INT_PTR hf, void FAR *pv, UINT cb)
  270. {
  271. return (((CFDIFile *) hf)->Write(pv,cb));
  272. }
  273. long FAR DIAMONDAPI fdi_seek(INT_PTR hf, long dist, int seektype)
  274. {
  275. return (((CFDIFile *) hf)->Seek(dist,seektype));
  276. }
  277. int FAR DIAMONDAPI fdi_close(INT_PTR hf)
  278. {
  279. int nRes;
  280. CFDIFile *pff = (CFDIFile *) hf;
  281. nRes = pff->Close();
  282. delete pff;
  283. return (nRes);
  284. }
  285. INT_PTR FAR DIAMONDAPI fdi_notify(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pfdin)
  286. {
  287. NotifyArgs *pnaArgs = (NotifyArgs *) pfdin->pv;
  288. BOOL bRes;
  289. switch (fdint)
  290. {
  291. case fdintCOPY_FILE:
  292. {
  293. InstallType itType;
  294. TCHAR szTmp[MAX_PATH+1];
  295. LPTSTR pszExt; // file extension
  296. PFILEPROCESSINFO pFPI;
  297. MYDBG(("fdi_notify() fdint=fdintCOPY_FILE, psz1=%s, cb=%u.",pfdin->psz1,pfdin->cb));
  298. if (lstrlen(pnaArgs->pdaArgs->szCabDir)+lstrlen(pfdin->psz1)+1>sizeof(szTmp)/sizeof(TCHAR)-1)
  299. {
  300. MYDBG(("fdi_notify() szCabDir=%s+pszFile=%s exceeds MAX_PATH.",pnaArgs->pdaArgs->szCabDir,pfdin->psz1));
  301. return (-1);
  302. }
  303. lstrcpy(szTmp,pnaArgs->pdaArgs->szCabDir);
  304. if (szTmp[0] && (GetLastChar(szTmp) != '\\'))
  305. {
  306. lstrcat(szTmp,TEXT("\\"));
  307. }
  308. lstrcat(szTmp,pfdin->psz1);
  309. if (!(pnaArgs->dwAppFlags & AF_NO_EXEINCAB) && (lstrcmpi(pfdin->psz1,c_pszExeFile) == 0))
  310. {
  311. //
  312. // Its a .EXE, note the fact for later processing
  313. //
  314. itType = itInvalid; // currently an invalid type
  315. pnaArgs->pdaArgs->fContainsExeOrInf = TRUE;
  316. }
  317. else if (!(pnaArgs->dwAppFlags & AF_NO_INFINCAB) && (lstrcmpi(pfdin->psz1,c_pszInfFile) == 0))
  318. {
  319. //
  320. // Its a .INF, note the fact for later processing
  321. //
  322. itType = itInvalid; // currently an invalid type
  323. pnaArgs->pdaArgs->fContainsExeOrInf = TRUE;
  324. }
  325. else if (!(pnaArgs->dwAppFlags & AF_NO_PBDINCAB) && (lstrcmpi(pfdin->psz1,c_pszPbdFile) == 0))
  326. {
  327. //
  328. // Its a .PBD, note the fact for later processing
  329. //
  330. itType = itPbdInCab;
  331. }
  332. else if ((pszExt = CmStrchr(pfdin->psz1, TEXT('.'))) && (lstrcmpi(pszExt+1, c_pszPbk) == 0))
  333. {
  334. *pszExt = TEXT('\0');
  335. // if the PBK is not for this service, we don't use it.
  336. if (lstrcmpi(pfdin->psz1, pnaArgs->pdaArgs->pszPhoneBookName) != 0)
  337. {
  338. itType = itInvalid;
  339. }
  340. else
  341. {
  342. itType = itPbkInCab;
  343. }
  344. // restore the filename
  345. *pszExt = TEXT('.');
  346. }
  347. else if ((pszExt = CmStrchr(pfdin->psz1, TEXT('.'))) && (lstrcmpi(pszExt+1, c_pszPbr) == 0))
  348. {
  349. *pszExt = TEXT('\0');
  350. // if the PBR is not for this service, we don't use it.
  351. if (lstrcmpi(pfdin->psz1, pnaArgs->pdaArgs->pszPhoneBookName) != 0)
  352. {
  353. itType = itInvalid;
  354. }
  355. else
  356. {
  357. itType = itPbrInCab;
  358. }
  359. // restore the filename
  360. *pszExt = TEXT('.');
  361. // save the name in pdaArgs
  362. // if (!(pnaArgs->pdaArgs->pszNewPbrFile = CmStrCpyAlloc(pfdin->psz1)))
  363. // {
  364. // MYDBG((TEXT("fdi_notify(): CmStrCpyAlloc for pszNewPbrFile failed.")));
  365. // return -1;
  366. // }
  367. }
  368. else if (lstrcmpi(pfdin->psz1, c_pszVerFile) == 0)
  369. {
  370. // a version file - we don't process it. We'll read the version in fdintCLOSE_FILE_INFO
  371. itType = itInvalid;
  372. }
  373. else
  374. {
  375. itType = itInvalid;
  376. }
  377. // create a file process info. add one to the existing list.
  378. if (itType != itInvalid)
  379. {
  380. if (!pnaArgs->pdaArgs->rgfpiFileProcessInfo)
  381. pFPI = (PFILEPROCESSINFO)CmMalloc(sizeof(FILEPROCESSINFO));
  382. else
  383. pFPI = (PFILEPROCESSINFO)CmRealloc(pnaArgs->pdaArgs->rgfpiFileProcessInfo,
  384. (pnaArgs->pdaArgs->dwNumFilesToProcess+1)*sizeof(FILEPROCESSINFO));
  385. if (!pFPI)
  386. {
  387. MYDBG((TEXT("fdi_notify(): Malloc(FILEPROCESSINFO) failed.")));
  388. return -1;
  389. }
  390. pnaArgs->pdaArgs->rgfpiFileProcessInfo = pFPI;
  391. pnaArgs->pdaArgs->dwNumFilesToProcess++;
  392. pFPI[pnaArgs->pdaArgs->dwNumFilesToProcess-1].itType = itType;
  393. pFPI[pnaArgs->pdaArgs->dwNumFilesToProcess-1].pszFile = CmStrCpyAlloc(pfdin->psz1);
  394. }
  395. // Do standard fdintCOPY_FILE processing, create the file and return the handle
  396. CFDIFileFile *pfff;
  397. pfff = new CFDIFileFile;
  398. if (!pfff)
  399. {
  400. MYDBG(("fdi_notify() new CFDIFileFile failed."));
  401. return (-1);
  402. }
  403. bRes = pfff->CreateFile(szTmp,GENERIC_WRITE,FILE_SHARE_READ,CREATE_NEW,FILE_ATTRIBUTE_NORMAL,0);
  404. if (!bRes)
  405. {
  406. delete pfff;
  407. return (-1);
  408. }
  409. return ((INT_PTR)pfff);
  410. }
  411. case fdintCLOSE_FILE_INFO:
  412. {
  413. int iRes;
  414. TCHAR szTmp[MAX_PATH+1];
  415. // Append file name to cab dir
  416. lstrcpy(szTmp,pnaArgs->pdaArgs->szCabDir);
  417. if (szTmp[0] && (GetLastChar(szTmp) != '\\'))
  418. {
  419. lstrcat(szTmp,TEXT("\\"));
  420. }
  421. lstrcat(szTmp,pfdin->psz1);
  422. // Set the date and time to the original file time not the current time
  423. FILETIME ftTmp;
  424. FILETIME ftTime;
  425. bRes = DosDateTimeToFileTime(pfdin->date,pfdin->time,&ftTmp);
  426. MYDBGTST(!bRes,("fdi_notify() DosDateTimeToFileTime(%u,%u) failed, GLE=%u.",pfdin->date,pfdin->time,GetLastError()));
  427. bRes = LocalFileTimeToFileTime(&ftTmp,&ftTime);
  428. MYDBGTST(!bRes,("fdi_notify() LocalFileTimeToFileTime() failed, GLE=%u.",GetLastError()));
  429. bRes = SetFileTime(((CFDIFile *) (pfdin->hf))->GetHandle(),&ftTime,&ftTime,&ftTime);
  430. MYDBGTST(!bRes,("fdi_notify() SetFileTime() failed, GLE=%u.",GetLastError()));
  431. iRes = fdi_close(pfdin->hf);
  432. // If this is the version file, get the version number
  433. if (lstrcmpi(pfdin->psz1,c_pszVerFile) == 0)
  434. {
  435. pnaArgs->pdaArgs->pszVerNew = GetVersionFromFile(szTmp);
  436. }
  437. // Set file attributes according to original file attribs
  438. bRes = SetFileAttributes(szTmp,pfdin->attribs);
  439. MYDBGTST(!bRes,("fdi_notify() SetFileAttributes(%s,%u) failed, GLE=%u.",szTmp,pfdin->attribs,GetLastError()));
  440. return ((iRes==0)?TRUE:FALSE);
  441. }
  442. case fdintNEXT_CABINET:
  443. MYDBG(("fdi_notify_scan() spanning cabinets is not supported."));
  444. return (-1);
  445. default:
  446. MYDBG(("fdi_notify_scan() fdint=%u.",fdint));
  447. break;
  448. }
  449. return (0);
  450. }