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.

401 lines
12 KiB

  1. #include "stdafx.h"
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <io.h>
  6. #include <fcntl.h>
  7. #include <dos.h>
  8. #include "cabfunc.h"
  9. #include "resource.h"
  10. #include "filestuff.h"
  11. #include "fdi.h"
  12. #include "setupapi.h"
  13. CString g_strExpandToDirectory;
  14. LRESULT WINAPI CabinetCallbackToExpand ( IN PVOID pMyInstallData, IN UINT Notification, IN UINT_PTR Param1, IN UINT_PTR Param2 )
  15. {
  16. LRESULT lRetVal = NO_ERROR;
  17. FILE_IN_CABINET_INFO *pInfo = NULL;
  18. CString strTargetName = g_strExpandToDirectory;
  19. strTargetName += '\\';
  20. switch(Notification)
  21. {
  22. case SPFILENOTIFY_FILEINCABINET:
  23. pInfo = (FILE_IN_CABINET_INFO *) Param1;
  24. lRetVal = FILEOP_DOIT; // Extract the file.
  25. strTargetName += pInfo->NameInCabinet;
  26. //pInfo->FullTargetName is define as TCHAR FullTargetName[MAX_PATH];
  27. _tcsncpy(pInfo->FullTargetName,strTargetName.GetBuffer(strTargetName.GetLength()),MAX_PATH);
  28. break;
  29. case SPFILENOTIFY_FILEEXTRACTED:
  30. lRetVal = NO_ERROR;
  31. break;
  32. case SPFILENOTIFY_NEEDNEWCABINET: // Cab file in the cab file we're looking at. Ignore it.
  33. lRetVal = NO_ERROR;
  34. break;
  35. }
  36. return lRetVal;
  37. }
  38. BOOL OpenCABFile(const CString& strCabPath,const CString& strExpandToDirectory)
  39. {
  40. g_strExpandToDirectory = strExpandToDirectory;
  41. if (!SetupIterateCabinet(strCabPath,0,(PSP_FILE_CALLBACK)CabinetCallbackToExpand,0))
  42. {
  43. return FALSE;
  44. }
  45. else
  46. {
  47. return TRUE;
  48. }
  49. }
  50. //---------------------------------------------------------------------------
  51. // This function looks in the specified directory for an NFO file. If it
  52. // finds one, it assigns it to filename and returns TRUE. This function
  53. // will only find the first NFO file in a directory.
  54. //
  55. // If an NFO file cannot be found, then we'll look for another file type
  56. // to open. Grab the string entry in the registry = "cabdefaultopen". An
  57. // example value would be "*.nfo|hwinfo.dat|*.dat|*.txt" which would be
  58. // interpreted as follows:
  59. //
  60. // 1. First look for any NFO file to open.
  61. // 2. Then try to open a file called "hwinfo.dat".
  62. // 3. Then try to open any file with a DAT extension.
  63. // 4. Then try for any TXT file.
  64. // 5. Finally, if none of these can be found, present an open dialog
  65. // to the user.
  66. //---------------------------------------------------------------------------
  67. LPCTSTR VAL_CABDEFAULTOPEN = _T("cabdefaultopen");
  68. LPCTSTR cszDirSeparator = _T("\\");
  69. BOOL IsDataspecFilePresent(CString strCabExplodedDir)
  70. {
  71. CStringList filesfound;
  72. DirectorySearch(_T("dataspec.xml"), strCabExplodedDir, filesfound);
  73. if (filesfound.GetHeadPosition() != NULL)
  74. {
  75. return TRUE;
  76. }
  77. return FALSE;
  78. }
  79. BOOL IsIncidentXMLFilePresent(CString strCabExplodedDir, CString strIncidentFileName)
  80. {
  81. CStringList filesfound;
  82. DirectorySearch(strIncidentFileName, strCabExplodedDir, filesfound);
  83. if (filesfound.GetHeadPosition() != NULL)
  84. {
  85. return TRUE;
  86. }
  87. return FALSE;
  88. }
  89. BOOL FindFileToOpen(const CString & destination, CString & filename)
  90. {
  91. CString strCABDefaultOpen, strRegBase, strDirectory;
  92. HKEY hkey;
  93. filename.Empty();
  94. strDirectory = destination;
  95. if (strDirectory.Right(1) != CString(cszDirSeparator))
  96. strDirectory += CString(cszDirSeparator);
  97. // Set up a fallback string of the NFO file type, in case we can't
  98. // find the registry entry.
  99. strCABDefaultOpen.LoadString(IDS_DEFAULTEXTENSION);
  100. strCABDefaultOpen = CString("*.") + strCABDefaultOpen;
  101. // Load the string of files and file types to open from the registry.
  102. strRegBase.LoadString(IDS_MSI_REG_BASE);
  103. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, strRegBase, 0, KEY_READ, &hkey) == ERROR_SUCCESS)
  104. {
  105. char szData[MAX_PATH];
  106. DWORD dwType, dwSize = MAX_PATH;
  107. if (RegQueryValueEx(hkey, VAL_CABDEFAULTOPEN, NULL, &dwType, (LPBYTE) szData, &dwSize) == ERROR_SUCCESS)
  108. if (dwType == REG_SZ)
  109. strCABDefaultOpen = szData;
  110. RegCloseKey(hkey);
  111. }
  112. // Look through each of the potential files and file types. If we find
  113. // a match, return TRUE after setting filename appropriately. Note that
  114. // we need to recurse down through directories.
  115. CString strFileSpec;
  116. CStringList filesfound;
  117. POSITION pos;
  118. while (!strCABDefaultOpen.IsEmpty())
  119. {
  120. if (strCABDefaultOpen.Find('|') == -1)
  121. strFileSpec = strCABDefaultOpen;
  122. else
  123. strFileSpec = strCABDefaultOpen.Left(strCABDefaultOpen.Find('|'));
  124. filesfound.RemoveAll();
  125. DirectorySearch(strFileSpec, strDirectory, filesfound);
  126. pos = filesfound.GetHeadPosition();
  127. if (pos != NULL)
  128. {
  129. filename = filesfound.GetNext(pos);
  130. return TRUE;
  131. }
  132. strCABDefaultOpen = strCABDefaultOpen.Right(strCABDefaultOpen.GetLength() - strFileSpec.GetLength());
  133. if (strCABDefaultOpen.Find('|') == 0)
  134. strCABDefaultOpen = strCABDefaultOpen.Right(strCABDefaultOpen.GetLength() - 1);
  135. }
  136. //a-kjaw
  137. ////Look for incident.xml file. It has to be an unicode file.
  138. strCABDefaultOpen = _T("*.XML");
  139. TCHAR pBuf[MAX_PATH];
  140. WCHAR pwBuf[MAX_PATH];
  141. HANDLE handle;
  142. DWORD dw;
  143. while (!strCABDefaultOpen.IsEmpty())
  144. {
  145. if (strCABDefaultOpen.Find('|') == -1)
  146. strFileSpec = strCABDefaultOpen;
  147. else
  148. strFileSpec = strCABDefaultOpen.Left(strCABDefaultOpen.Find('|'));
  149. filesfound.RemoveAll();
  150. DirectorySearch(strFileSpec, strDirectory, filesfound);
  151. pos = filesfound.GetHeadPosition();
  152. while (pos != NULL)
  153. {
  154. filename = filesfound.GetNext(pos);
  155. handle = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  156. if (INVALID_HANDLE_VALUE == handle)
  157. continue;
  158. ReadFile(handle , pBuf , 1 , &dw , NULL);
  159. if( pBuf[0] == _T('<'))
  160. {
  161. do
  162. {
  163. ReadFile(handle , pBuf , _tcslen(_T("MachineID")) * sizeof(TCHAR) , &dw , NULL);
  164. if(_tcsicmp(pBuf , _T("MachineID")) == 0)
  165. {
  166. CloseHandle( handle );
  167. return TRUE;
  168. }
  169. else
  170. {
  171. SetFilePointer(handle , (1 - _tcslen(_T("MachineID")) )* sizeof(TCHAR) , 0 , FILE_CURRENT );
  172. }
  173. }while( dw == _tcslen(_T("MachineID")) );
  174. }
  175. else //Unicode?
  176. {
  177. ReadFile(handle , pwBuf , 1 , &dw , NULL);
  178. do
  179. {
  180. ReadFile(handle , pwBuf , lstrlenW(L"MachineID") * sizeof(WCHAR) , &dw , NULL);
  181. pwBuf[ lstrlenW(L"MachineID") ] = L'\0';
  182. if(lstrcmpiW(pwBuf , L"MachineID") == 0)
  183. {
  184. CloseHandle( handle );
  185. return TRUE;
  186. }
  187. else
  188. {
  189. SetFilePointer(handle , (1 - lstrlenW(L"MachineID"))* sizeof(WCHAR) , 0 , FILE_CURRENT );
  190. }
  191. }while( dw == _tcslen(_T("MachineID")) * sizeof(WCHAR) );
  192. }
  193. CloseHandle( handle );
  194. }
  195. strCABDefaultOpen = strCABDefaultOpen.Right(strCABDefaultOpen.GetLength() - strFileSpec.GetLength());
  196. if (strCABDefaultOpen.Find('|') == 0)
  197. strCABDefaultOpen = strCABDefaultOpen.Right(strCABDefaultOpen.GetLength() - 1);
  198. }
  199. return FALSE;
  200. }
  201. //---------------------------------------------------------------------------
  202. // DirectorySearch is used to locate all of the files in a directory or
  203. // one of its subdirectories which match a file spec.
  204. //---------------------------------------------------------------------------
  205. void DirectorySearch(const CString & strSpec, const CString & strDir, CStringList &results)
  206. {
  207. // Look for all of the files which match the file spec in the directory
  208. // specified by strDir.
  209. WIN32_FIND_DATA finddata;
  210. CString strSearch, strDirectory;
  211. strDirectory = strDir;
  212. if (strDirectory.Right(1) != CString(cszDirSeparator)) strDirectory += CString(cszDirSeparator);
  213. strSearch = strDirectory + strSpec;
  214. HANDLE hFind = FindFirstFile(strSearch, &finddata);
  215. if (hFind != INVALID_HANDLE_VALUE)
  216. {
  217. do
  218. {
  219. results.AddHead(strDirectory + CString(finddata.cFileName));
  220. } while (FindNextFile(hFind, &finddata));
  221. FindClose(hFind);
  222. }
  223. // Now call this function recursively, with each of the subdirectories.
  224. strSearch = strDirectory + CString(_T("*"));
  225. hFind = FindFirstFile(strSearch, &finddata);
  226. if (hFind != INVALID_HANDLE_VALUE)
  227. {
  228. do
  229. {
  230. if (finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  231. if (::_tcscmp(finddata.cFileName, _T(".")) != 0 && ::_tcscmp(finddata.cFileName, _T("..")) != 0)
  232. DirectorySearch(strSpec, strDirectory + CString(finddata.cFileName), results);
  233. } while (FindNextFile(hFind, &finddata));
  234. FindClose(hFind);
  235. }
  236. }
  237. //---------------------------------------------------------------------------
  238. // This function gets the directory in which to put exploded CAB files.
  239. // This will be the same directory each time, so this function will create
  240. // the directory (if necessary) and delete any files in the directory.
  241. //---------------------------------------------------------------------------
  242. BOOL GetCABExplodeDir(CString &destination, BOOL fDeleteFiles, const CString & strDontDelete)
  243. {
  244. CString strMSInfoDir, strExplodeTo, strSubDirName;
  245. // Determine the temporary path and add on a subdir name.
  246. TCHAR szTempDir[MAX_PATH];
  247. if (::GetTempPath(MAX_PATH, szTempDir) > MAX_PATH)
  248. {
  249. destination = _T("");
  250. return FALSE;
  251. }
  252. strSubDirName.LoadString(IDS_CAB_DIR_NAME);
  253. strExplodeTo = szTempDir;
  254. if (strExplodeTo.Right(1) == CString(cszDirSeparator))
  255. strExplodeTo = strExplodeTo + strSubDirName;
  256. else
  257. strExplodeTo = strExplodeTo + CString(cszDirSeparator) + strSubDirName;
  258. // Kill the directory if it already exists.
  259. if (fDeleteFiles)
  260. KillDirectory(strExplodeTo, strDontDelete);
  261. // Create the subdirectory.
  262. if (!CreateDirectoryEx(szTempDir, strExplodeTo, NULL))
  263. {
  264. if (GetLastError() != ERROR_ALREADY_EXISTS)
  265. {
  266. // MSIError(IDS_GENERAL_ERROR, "couldn't create the target directory");
  267. destination = "";
  268. return FALSE;
  269. }
  270. }
  271. destination = strExplodeTo;
  272. return TRUE;
  273. }
  274. //---------------------------------------------------------------------------
  275. // This functions kills a directory by recursively deleting files and
  276. // subdirectories.
  277. //---------------------------------------------------------------------------
  278. void KillDirectory(const CString & strDir, const CString & strDontDelete)
  279. {
  280. CString strDirectory = strDir;
  281. if (strDirectory.Right(1) == CString(cszDirSeparator))
  282. strDirectory = strDirectory.Left(strDirectory.GetLength() - 1);
  283. // Delete any files in directory.
  284. CString strFilesToDelete = strDirectory + CString(_T("\\*.*"));
  285. CString strDeleteFile;
  286. WIN32_FIND_DATA filedata;
  287. BOOL bFound = TRUE;
  288. HANDLE hFindFile = FindFirstFile(strFilesToDelete, &filedata);
  289. while (hFindFile != INVALID_HANDLE_VALUE && bFound)
  290. {
  291. if ((filedata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0L)
  292. {
  293. strDeleteFile = strDirectory + CString(cszDirSeparator) + filedata.cFileName;
  294. if (strDontDelete.CompareNoCase(strDeleteFile) != 0)
  295. {
  296. ::SetFileAttributes(strDeleteFile, FILE_ATTRIBUTE_NORMAL);
  297. ::DeleteFile(strDeleteFile);
  298. }
  299. }
  300. bFound = FindNextFile(hFindFile, &filedata);
  301. }
  302. FindClose(hFindFile);
  303. // Now call this function on any subdirectories in this directory.
  304. CString strSearch = strDirectory + CString(_T("\\*"));
  305. hFindFile = FindFirstFile(strSearch, &filedata);
  306. if (hFindFile != INVALID_HANDLE_VALUE)
  307. {
  308. do
  309. {
  310. if (filedata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  311. if (::_tcscmp(filedata.cFileName, _T(".")) != 0 && ::_tcscmp(filedata.cFileName, _T("..")) != 0)
  312. KillDirectory(strDirectory + CString(cszDirSeparator) + CString(filedata.cFileName));
  313. } while (FindNextFile(hFindFile, &filedata));
  314. FindClose(hFindFile);
  315. }
  316. // Finally, remove this directory.
  317. ::RemoveDirectory(strDirectory);
  318. }