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.

398 lines
9.9 KiB

  1. #include <windows.h>
  2. #include "util.h"
  3. #ifndef ASSERT
  4. #if defined(_DEBUG) || defined(DEBUG)
  5. #define ASSERT(b) if(!b) MessageBox(NULL, "FAILED: #b", "ASSERT", MB_OK );
  6. #else
  7. #define ASSERT(b)
  8. #endif
  9. #endif
  10. #define MAX_STRING_RESOURCE_LEN 1024
  11. LPCSTR g_pszMsgBoxTitle = "HTML Help Dumper Tool";
  12. int MsgBox(int idString, UINT nType)
  13. {
  14. char szMsg[MAX_STRING_RESOURCE_LEN + 1];
  15. if (LoadString(GetModuleHandle(NULL), idString, szMsg,
  16. sizeof(szMsg)) == 0) {
  17. return 0;
  18. }
  19. return MessageBox(GetActiveWindow(), szMsg, g_pszMsgBoxTitle, nType);
  20. }
  21. int MsgBox(PCSTR pszMsg, UINT nType)
  22. {
  23. return MessageBox(GetActiveWindow(), pszMsg, g_pszMsgBoxTitle, nType);
  24. }
  25. PCSTR FindFilePortion( PCSTR pszFile )
  26. {
  27. PCSTR psz = strrchr(pszFile, '\\');
  28. if (psz)
  29. pszFile = psz + 1;
  30. psz = strrchr(pszFile, '/');
  31. if (psz)
  32. return psz + 1;
  33. psz = strrchr(pszFile, ':');
  34. return (psz ? psz + 1 : pszFile);
  35. }
  36. typedef enum { JAN=1, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC } MONTHS;
  37. int DaysInMonth(int nMonth, int nYear)
  38. {
  39. switch( nMonth ) {
  40. case SEP: case APR: case JUN: case NOV:
  41. return 30;
  42. case FEB:
  43. return (nYear % 4) == 0 ? 29 : 28; // handle leap year
  44. default:
  45. return 31;
  46. }
  47. }
  48. int JulianDate(int nDay, int nMonth, int nYear)
  49. {
  50. int nDayOfYear = 0;
  51. int iMonth;
  52. for( iMonth = JAN ; iMonth < nMonth ; iMonth++ )
  53. nDayOfYear += DaysInMonth(iMonth, nYear);
  54. return( (nYear % 10) * 1000 + nDayOfYear + nDay );
  55. }
  56. #define YRMASK 0xFE00
  57. #define YRSHIFT 9
  58. #define MONMASK 0x01E0
  59. #define MONSHIFT 5
  60. #define DAYMASK 0x001F
  61. #define DAYSHIFT 0
  62. #define HRMASK 0xF800
  63. #define HRSHIFT 11
  64. #define MINMASK 0x07E0
  65. #define MINSHIFT 5
  66. #define SECMASK 0x001F
  67. #define SECSHIFT 0
  68. HRESULT FileTimeToDateTimeString( FILETIME FileTime, LPTSTR pszDateTime )
  69. {
  70. HRESULT hr = S_FALSE;
  71. WORD wDosDate = 0;
  72. WORD wDosTime = 0;
  73. if( FileTimeToDosDateTime( &FileTime, &wDosDate, &wDosTime ) ) {
  74. DWORD dwDay = (wDosDate & DAYMASK) >> DAYSHIFT;
  75. DWORD dwMonth = (wDosDate & MONMASK) >> MONSHIFT;
  76. DWORD dwYear = (((wDosDate & YRMASK) >> YRSHIFT) + 80) % 100;
  77. DWORD dwHour = (wDosTime & HRMASK) >> HRSHIFT;
  78. DWORD dwMinute = (wDosTime & MINMASK) >> MINSHIFT;
  79. DWORD dwSecond = ((wDosTime & SECMASK) >> SECSHIFT) * 2;
  80. LPCSTR pszAMPM = NULL;
  81. if( dwHour >= 12 )
  82. pszAMPM = "PM";
  83. else
  84. pszAMPM = "AM";
  85. if( dwHour > 12 )
  86. dwHour -= 12;
  87. if( dwHour == 0 )
  88. dwHour = 12;
  89. wsprintf( pszDateTime, "%02d/%02d/%02d %02d:%02d %s",
  90. dwMonth, dwDay, dwYear, dwHour, dwMinute, pszAMPM );
  91. hr = S_OK;
  92. }
  93. return hr;
  94. }
  95. int FileTimeToJulianDate( FILETIME FileTime )
  96. {
  97. int iReturn = 0;
  98. WORD wDosDate = 0;
  99. WORD wDosTime = 0;
  100. if( FileTimeToDosDateTime( &FileTime, &wDosDate, &wDosTime ) ) {
  101. DWORD dwDay = (wDosDate & DAYMASK) >> DAYSHIFT;
  102. DWORD dwMonth = (wDosDate & MONMASK) >> MONSHIFT;
  103. DWORD dwYear = ((wDosDate & YRMASK) >> YRSHIFT) + 1980;
  104. iReturn = JulianDate( dwDay, dwMonth, dwYear );
  105. }
  106. return iReturn;
  107. }
  108. ///////////////////////////////////////////////////////////
  109. //
  110. // Get the windows directory for the system or the user
  111. //
  112. // Note, Windows NT Terminal Server has changed the system API
  113. // of GetWindowsDirectory to return a per-user system directory.
  114. // Inorder to determine this condtion we need to check kernel32
  115. // for the GetSystemWindowsDirectory API and if it exists use
  116. // this one instead.
  117. //
  118. UINT HHGetWindowsDirectory( LPSTR lpBuffer, UINT uSize, UINT uiType )
  119. {
  120. UINT uiReturn = 0;
  121. PFN_GETWINDOWSDIRECTORY pfnGetUsersWindowsDirectory = NULL;
  122. PFN_GETWINDOWSDIRECTORY pfnGetSystemWindowsDirectory = NULL;
  123. // determine which system API to call for each case
  124. HINSTANCE hInst = LoadLibrary( "Kernel32" );
  125. if( !hInst )
  126. return uiReturn;
  127. pfnGetSystemWindowsDirectory = (PFN_GETWINDOWSDIRECTORY) GetProcAddress( hInst, "GetSystemWindowsDirectoryA" );
  128. pfnGetUsersWindowsDirectory = (PFN_GETWINDOWSDIRECTORY) GetProcAddress( hInst, "GetWindowsDirectoryA" );
  129. ASSERT( pfnGetUsersWindowsDirectory ); // if NULL then we have a bug!
  130. if( !pfnGetSystemWindowsDirectory ) {
  131. pfnGetSystemWindowsDirectory = pfnGetUsersWindowsDirectory;
  132. }
  133. if( uiType == HH_SYSTEM_WINDOWS_DIRECTORY )
  134. uiReturn = pfnGetSystemWindowsDirectory( lpBuffer, uSize );
  135. else if( uiType == HH_USERS_WINDOWS_DIRECTORY )
  136. uiReturn = pfnGetUsersWindowsDirectory( lpBuffer, uSize );
  137. else
  138. uiReturn = 0;
  139. FreeLibrary( hInst );
  140. return uiReturn;
  141. }
  142. LPSTR CatPath(LPSTR lpTop, LPCSTR lpTail)
  143. {
  144. //
  145. // make sure we have a slash at the end of the first element
  146. //
  147. LPSTR p;
  148. p = lpTop + strlen(lpTop);
  149. p = CharPrev(lpTop,p);
  150. if (*p != '\\' && *p != '/')
  151. {
  152. strcat(lpTop,"\\");
  153. }
  154. //
  155. // strip any leading slash from the second element
  156. //
  157. while (*lpTail == '\\') lpTail = CharNext(lpTail);
  158. //
  159. // add them together
  160. //
  161. strcat(lpTop, lpTail);
  162. return lpTop;
  163. }
  164. #pragma data_seg(".text", "CODE")
  165. static const char txtGlobal[] = "global.col";
  166. static const char txtColReg[] = "hhcolreg.dat";
  167. static const char txtHelp[] = "help";
  168. static const char txtHHDat[] = "hh.dat";
  169. #pragma data_seg()
  170. ///////////////////////////////////////////////////////////
  171. //
  172. // Get the help directory
  173. //
  174. // Note, this is always relative to the system's windows
  175. // directory and not the user's windows directory.
  176. // See HHGetWindowsDirectory for details on this.
  177. //
  178. UINT HHGetHelpDirectory( LPTSTR lpBuffer, UINT uSize )
  179. {
  180. UINT uiReturn = 0;
  181. uiReturn = HHGetWindowsDirectory( lpBuffer, uSize );
  182. CatPath( lpBuffer, txtHelp );
  183. return uiReturn;
  184. }
  185. DWORD CreatePath(char *szPath)
  186. {
  187. char szTmp[MAX_PATH],*p,*q,szTmp2[MAX_PATH];
  188. DWORD dwErr;
  189. strcpy(szTmp2,szPath);
  190. memset(szTmp,0,sizeof(szTmp));
  191. q = szTmp2;
  192. p = szTmp;
  193. while (*q)
  194. {
  195. if (*q == '/' || *q == '\\')
  196. {
  197. if (szTmp[1] == ':' && strlen(szTmp) <= 3)
  198. {
  199. if(IsDBCSLeadByte(*q))
  200. {
  201. *p++ = *q++;
  202. if(*q)
  203. *p++ = *q++;
  204. }
  205. else
  206. *p++ = *q++;
  207. continue;
  208. }
  209. if (!::CreateDirectory(szTmp,0))
  210. {
  211. if ( (dwErr = GetLastError()) != ERROR_ALREADY_EXISTS)
  212. return(dwErr);
  213. }
  214. }
  215. if(IsDBCSLeadByte(*q))
  216. {
  217. *p++ = *q++;
  218. if(*q)
  219. *p++ = *q++;
  220. }
  221. else
  222. *p++ = *q++;
  223. }
  224. if (!::CreateDirectory(szTmp,0))
  225. {
  226. if ((dwErr = GetLastError()) != ERROR_ALREADY_EXISTS)
  227. return(dwErr);
  228. }
  229. return(FALSE);
  230. }
  231. ///////////////////////////////////////////////////////////
  232. //
  233. // Get the full pathname to the global collections file
  234. //
  235. // Note, this is in always in the system's help directory.
  236. //
  237. UINT HHGetGlobalCollectionPathname( LPTSTR lpBuffer, UINT uSize, BOOL *pbNewPath )
  238. {
  239. UINT uiReturn = 0;
  240. *pbNewPath = TRUE;
  241. uiReturn = HHGetHelpDataPath( lpBuffer );
  242. if (uiReturn != S_OK)
  243. {
  244. *pbNewPath = FALSE;
  245. uiReturn = HHGetHelpDirectory( lpBuffer, uSize );
  246. if( !IsDirectory(lpBuffer) )
  247. CreatePath( lpBuffer );
  248. }
  249. CatPath( lpBuffer, txtColReg );
  250. return uiReturn;
  251. }
  252. BOOL IsDirectory( LPCSTR lpszPathname )
  253. {
  254. DWORD dwAttribs = GetFileAttributes( lpszPathname );
  255. if( dwAttribs != (DWORD) -1 )
  256. if( dwAttribs & FILE_ATTRIBUTE_DIRECTORY )
  257. return TRUE;
  258. return FALSE;
  259. }
  260. static const char txtProfiles[] = "Profiles";
  261. static const char txtUser[] = "Default User";
  262. static const char txtAllUsers[] = "All Users";
  263. static const char txtApplicationData[] = "Application Data";
  264. static const char txtMicrosoft[] = "Microsoft";
  265. static const char txtHTMLHelp[] = "HTML Help";
  266. typedef HRESULT (WINAPI *PFN_SHGETFOLDERPATH)( HWND hWnd, int nFolder, HANDLE hToken, DWORD dwFlags, LPTSTR pszPath );
  267. #ifndef CSIDL_FLAG_CREATE
  268. #define CSIDL_COMMON_APPDATA 0x0023
  269. #define CSIDL_FLAG_CREATE 0x8000
  270. #endif
  271. ///////////////////////////////////////////////////////////
  272. //
  273. // Get the full path to where the common help data files lives
  274. // hhcolreg.dat, *.chw and *.chs
  275. //
  276. // Note, if the subdirectories of the path does not exist
  277. // we will create them
  278. //
  279. HRESULT HHGetHelpDataPath( LPSTR pszPath )
  280. {
  281. HRESULT hResult = S_OK;
  282. PFN_SHGETFOLDERPATH pfnSHGetFolderPath = NULL;
  283. HINSTANCE hInst = LoadLibrary( "Shell32" );
  284. if( !hInst )
  285. return S_FALSE;
  286. pfnSHGetFolderPath = (PFN_SHGETFOLDERPATH) GetProcAddress( hInst, "SHGetFolderPathA" );
  287. // if this function does not exist then we need to similate the return path of
  288. // "%windir%\Profiles\All Users\Application Data"
  289. if( pfnSHGetFolderPath ) {
  290. // now call it
  291. hResult = pfnSHGetFolderPath( NULL, CSIDL_FLAG_CREATE | CSIDL_COMMON_APPDATA, NULL, 0, pszPath);
  292. if (pszPath[0] == NULL)
  293. {
  294. FreeLibrary( hInst ); // since we already have a copy of Shell32 loaded, free it
  295. return S_FALSE;
  296. }
  297. }
  298. else
  299. {
  300. FreeLibrary( hInst ); // since we already have a copy of Shell32 loaded, free it
  301. return S_FALSE;
  302. }
  303. FreeLibrary( hInst ); // since we already have a copy of Shell32 loaded, free it
  304. // append "Microsoft"
  305. CatPath( pszPath, txtMicrosoft );
  306. if( !IsDirectory(pszPath) )
  307. if( !CreateDirectory( pszPath, NULL ) )
  308. return S_FALSE;
  309. // append "HTML Help"
  310. CatPath( pszPath, txtHTMLHelp );
  311. if( !IsDirectory(pszPath) )
  312. if( !CreateDirectory( pszPath, NULL ) )
  313. return S_FALSE;
  314. return hResult;
  315. }
  316. ///////////////////////////////////////////////////////////
  317. //
  318. // Get the full pathname to the user's data file
  319. //
  320. // Note, this is always relative to the users's windows
  321. // directory and not the system's windows directory.
  322. // See HHGetWindowsDirectory for details on this.
  323. //
  324. UINT HHGetUsersDataPathname( LPTSTR lpBuffer, UINT uSize )
  325. {
  326. UINT uiReturn = 0;
  327. uiReturn = HHGetWindowsDirectory( lpBuffer, uSize, HH_USERS_WINDOWS_DIRECTORY );
  328. CatPath( lpBuffer, txtHHDat );
  329. return uiReturn;
  330. }