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.

480 lines
12 KiB

  1. //+--------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1996.
  5. //
  6. // File: util.cxx
  7. //
  8. // Contents: DRT support routines
  9. //
  10. //---------------------------------------------------------------
  11. #include "headers.cxx"
  12. #include <stdarg.h>
  13. #ifdef _WIN32
  14. #include <direct.h>
  15. #include <io.h>
  16. #else
  17. #include "winio.hxx"
  18. #endif
  19. #define DEFAULT_DATA_DIR "."
  20. BOOL fExitOnFail = TRUE;
  21. char szOrigDir[_MAX_PATH] = ".";
  22. // Preserve the current directory and change
  23. // directory into the data directory
  24. void SetData(void)
  25. {
  26. char *pszDataDir;
  27. _getcwd(szOrigDir, _MAX_PATH);
  28. pszDataDir = getenv("DRTDATA");
  29. if (pszDataDir == NULL)
  30. pszDataDir = DEFAULT_DATA_DIR;
  31. _chdir(pszDataDir);
  32. }
  33. // Clean up the data directory
  34. void CleanData(void)
  35. {
  36. _unlink(pszDRTDF);
  37. }
  38. // Restore the original directory
  39. void UnsetData(void)
  40. {
  41. _chdir(szOrigDir);
  42. }
  43. // Output a message if fVerbose is true
  44. void out(char *fmt, ...)
  45. {
  46. va_list args;
  47. if (fVerbose)
  48. {
  49. va_start(args, fmt);
  50. vprintf(fmt, args);
  51. va_end(args);
  52. }
  53. }
  54. // internal error print
  55. void _errorprint (char *fmt, va_list args)
  56. {
  57. printf("** Fatal error **: ");
  58. vprintf(fmt, args);
  59. }
  60. // error print
  61. void errorprint (char *fmt, ...)
  62. {
  63. va_list args;
  64. va_start (args, fmt);
  65. _errorprint (fmt, args);
  66. va_end (args);
  67. }
  68. // Print out an error message and terminate the DRT
  69. void error(int code, char *fmt, ...)
  70. {
  71. va_list args;
  72. va_start(args, fmt);
  73. _errorprint (fmt, args);
  74. va_end(args);
  75. CleanData();
  76. UnsetData();
  77. exit(code);
  78. }
  79. // Converts a TCHAR string to a char pointer in a temporary buffer
  80. // This implementation treats the conversion buffer as a circular
  81. // buffer so more than one string can be held (depending on the size
  82. // of the strings)
  83. #define BUFSIZE 1024
  84. char *OlecsOut(OLECHAR const *ptcs)
  85. {
  86. #ifdef OLEWIDECHAR
  87. static char szBuffer[BUFSIZE];
  88. static char *pszBuf = szBuffer;
  89. char *pszTmp;
  90. if (ptcs == NULL)
  91. return NULL;
  92. if (wcslen(ptcs) >= (size_t)(BUFSIZE-(pszBuf-szBuffer)))
  93. pszBuf = szBuffer;
  94. OLETOA(ptcs, pszBuf, BUFSIZE);
  95. szBuffer[BUFSIZE-1] = 0;
  96. pszTmp = pszBuf;
  97. pszBuf += strlen(pszBuf)+1;
  98. return pszTmp;
  99. #else
  100. return (char *)ptcs;
  101. #endif
  102. }
  103. typedef struct
  104. {
  105. SCODE sc;
  106. char *text;
  107. } StatusCodeText;
  108. static StatusCodeText scodes[] =
  109. {
  110. S_OK, "S_OK",
  111. S_FALSE, "S_FALSE",
  112. STG_E_INVALIDFUNCTION, "STG_E_INVALIDFUNCTION",
  113. STG_E_FILENOTFOUND, "STG_E_FILENOTFOUND",
  114. STG_E_PATHNOTFOUND, "STG_E_PATHNOTFOUND",
  115. STG_E_TOOMANYOPENFILES, "STG_E_TOOMANYOPENFILES",
  116. STG_E_ACCESSDENIED, "STG_E_ACCESSDENIED",
  117. STG_E_INVALIDHANDLE, "STG_E_INVALIDHANDLE",
  118. STG_E_INSUFFICIENTMEMORY, "STG_E_INSUFFICIENTMEMORY",
  119. STG_E_INVALIDPOINTER, "STG_E_INVALIDPOINTER",
  120. STG_E_NOMOREFILES, "STG_E_NOMOREFILES",
  121. STG_E_DISKISWRITEPROTECTED, "STG_E_DISKISWRITEPROTECTED",
  122. STG_E_SEEKERROR, "STG_E_SEEKERROR",
  123. STG_E_WRITEFAULT, "STG_E_WRITEFAULT",
  124. STG_E_READFAULT, "STG_E_READFAULT",
  125. STG_E_SHAREVIOLATION, "STG_E_SHAREVIOLATION",
  126. STG_E_LOCKVIOLATION, "STG_E_LOCKVIOLATION",
  127. STG_E_FILEALREADYEXISTS, "STG_E_FILEALREADYEXISTS",
  128. STG_E_INVALIDPARAMETER, "STG_E_INVALIDPARAMETER",
  129. STG_E_MEDIUMFULL, "STG_E_MEDIUMFULL",
  130. STG_E_ABNORMALAPIEXIT, "STG_E_ABNORMALAPIEXIT",
  131. STG_E_INVALIDHEADER, "STG_E_INVALIDHEADER",
  132. STG_E_INVALIDNAME, "STG_E_INVALIDNAME",
  133. STG_E_UNKNOWN, "STG_E_UNKNOWN",
  134. STG_E_UNIMPLEMENTEDFUNCTION, "STG_E_UNIMPLEMENTEDFUNCTION",
  135. STG_E_INVALIDFLAG, "STG_E_INVALIDFLAG",
  136. STG_E_INUSE, "STG_E_INUSE",
  137. STG_E_NOTCURRENT, "STG_E_NOTCURRENT",
  138. STG_E_REVERTED, "STG_E_REVERTED",
  139. STG_E_CANTSAVE, "STG_E_CANTSAVE",
  140. STG_E_OLDFORMAT, "STG_E_OLDFORMAT",
  141. STG_E_OLDDLL, "STG_E_OLDDLL",
  142. STG_E_SHAREREQUIRED, "STG_E_SHAREREQUIRED",
  143. STG_E_NOTFILEBASEDSTORAGE, "STG_E_NOTFILEBASEDSTORAGE",
  144. STG_S_CONVERTED, "STG_S_CONVERTED"
  145. };
  146. #define NSCODETEXT (sizeof(scodes)/sizeof(scodes[0]))
  147. // Convert a status code to text
  148. char *ScText(SCODE sc)
  149. {
  150. int i;
  151. for (i = 0; i<NSCODETEXT; i++)
  152. if (scodes[i].sc == sc)
  153. return scodes[i].text;
  154. return "?";
  155. }
  156. // Output a call result and check for failure
  157. HRESULT Result(HRESULT hr)
  158. {
  159. SCODE sc;
  160. sc = DfGetScode(hr);
  161. out(" - %s (0x%lX)\n", ScText(sc), sc);
  162. if (FAILED(sc) && fExitOnFail)
  163. error(EXIT_BADSC, "Unexpected call failure\n");
  164. return hr;
  165. }
  166. // Perform Result() when the expectation is failure
  167. HRESULT IllResult(char *pszText, HRESULT hr)
  168. {
  169. SCODE sc;
  170. sc = DfGetScode(hr);
  171. out("%s - %s (0x%lX)\n", pszText, ScText(sc), sc);
  172. if (SUCCEEDED(sc) && fExitOnFail)
  173. error(EXIT_BADSC, "Unexpected call success\n");
  174. return hr;
  175. }
  176. // Check whether a given storage has a certain
  177. // structure or not
  178. // Structure is given as a string with elements:
  179. // <Type><Name><Options>[,...]
  180. // Type - d for docfile and s for stream
  181. // Name - Characters up to a '(' or ','
  182. // Options - For a docfile, you can specify a recursive check
  183. // in parentheses
  184. //
  185. // Example: dDocfile(sStream,dDocfile)
  186. char *VerifyStructure(IStorage *pstg, char *pszStructure)
  187. {
  188. char szName[CWCSTORAGENAME], *psz;
  189. IStorage *pstgChild;
  190. char chType;
  191. SCODE sc;
  192. CStrList sl;
  193. SStrEntry *pse;
  194. IEnumSTATSTG *penm;
  195. STATSTG stat;
  196. OLECHAR atcName[CWCSTORAGENAME];
  197. if (FAILED(sc = DfGetScode(pstg->EnumElements(0, NULL, 0, &penm))))
  198. error(EXIT_BADSC, "VerifyStructure: Unable to create enumerator - "
  199. "%s (0x%lX)\n", ScText(sc), sc);
  200. for (;;)
  201. {
  202. sc = DfGetScode(penm->Next(1, &stat, NULL));
  203. if (sc == S_FALSE)
  204. break;
  205. else if (FAILED(sc))
  206. error(EXIT_BADSC, "VerifyStructure: Unable to enumerate - "
  207. "%s (0x%lX)\n", ScText(sc), sc);
  208. pse = sl.Add(stat.pwcsName);
  209. if (pse == NULL)
  210. error(EXIT_OOM, "VerifyStructure: Unable to allocate string\n");
  211. pse->user.dw = stat.type;
  212. drtMemFree(stat.pwcsName);
  213. }
  214. penm->Release();
  215. while (*pszStructure && *pszStructure != ')')
  216. {
  217. chType = *pszStructure++;
  218. psz = szName;
  219. while (*pszStructure && *pszStructure != '(' &&
  220. *pszStructure != ')' && *pszStructure != ',')
  221. *psz++ = *pszStructure++;
  222. *psz = 0;
  223. ATOOLE(szName, atcName, CWCSTORAGENAME);
  224. pse = sl.Find(atcName);
  225. if (pse == NULL)
  226. error(EXIT_BADSC, "VerifyStructure: '%s' not found\n", szName);
  227. switch(chType)
  228. {
  229. case 'd':
  230. if (pse->user.dw != STGTY_STORAGE)
  231. error(EXIT_BADSC, "VerifyStructure: '%s' is not a storage\n",
  232. szName);
  233. sc = DfGetScode(pstg->OpenStorage(atcName, NULL,
  234. STGP(STGM_READWRITE), NULL,
  235. 0, &pstgChild));
  236. if (FAILED(sc))
  237. error(EXIT_BADSC, "VerifyStructure: can't open storage "
  238. "'%s' - %s\n", szName, ScText(sc));
  239. if (*pszStructure == '(')
  240. pszStructure = VerifyStructure(pstgChild, pszStructure+1)+1;
  241. pstgChild->Release();
  242. break;
  243. case 's':
  244. if (pse->user.dw != STGTY_STREAM)
  245. error(EXIT_BADSC, "VerifyStructure: '%s' is not a stream\n",
  246. szName);
  247. break;
  248. }
  249. sl.Remove(pse);
  250. if (*pszStructure == ',')
  251. pszStructure++;
  252. }
  253. for (pse = sl.GetHead(); pse; pse = pse->pseNext)
  254. error(EXIT_BADSC, "VerifyStructure: additional member '%s'\n",
  255. OlecsOut(pse->atc));
  256. return pszStructure;
  257. }
  258. // Creates a structure using the same syntax
  259. // as VerifyStructure
  260. char *CreateStructure(IStorage *pstg, char *pszStructure)
  261. {
  262. char szName[CWCSTORAGENAME], *psz;
  263. IStorage *pstgChild;
  264. IStream *pstmChild;
  265. char chType;
  266. SCODE sc;
  267. OLECHAR atcName[CWCSTORAGENAME];
  268. while (*pszStructure && *pszStructure != ')')
  269. {
  270. chType = *pszStructure++;
  271. psz = szName;
  272. while (*pszStructure && *pszStructure != '(' &&
  273. *pszStructure != ')' && *pszStructure != ',')
  274. *psz++ = *pszStructure++;
  275. *psz = 0;
  276. ATOOLE(szName, atcName, CWCSTORAGENAME);
  277. switch(chType)
  278. {
  279. case 'd':
  280. sc = DfGetScode(pstg->CreateStorage(atcName, STGP(STGM_READWRITE),
  281. 0, 0, &pstgChild));
  282. if (FAILED(sc))
  283. error(EXIT_BADSC, "CreateStructure: can't create storage "
  284. "'%s' - %s\n", szName, ScText(sc));
  285. if (*pszStructure == '(')
  286. pszStructure = CreateStructure(pstgChild, pszStructure+1)+1;
  287. pstgChild->Release();
  288. break;
  289. case 's':
  290. sc = DfGetScode(pstg->CreateStream(atcName, STMP(STGM_READWRITE),
  291. 0, 0, &pstmChild));
  292. if (FAILED(sc))
  293. error(EXIT_BADSC, "CreateStructure: can't create stream "
  294. "'%s' - %s\n", szName, ScText(sc));
  295. pstmChild->Release();
  296. break;
  297. }
  298. if (*pszStructure == ',')
  299. pszStructure++;
  300. }
  301. pstg->Commit(0);
  302. return pszStructure;
  303. }
  304. // Verifies the fields of a STATSTG
  305. void VerifyStat(STATSTG *pstat, OLECHAR *ptcsName, DWORD type, DWORD grfMode)
  306. {
  307. if (ptcsName == NULL)
  308. {
  309. if (pstat->pwcsName != NULL)
  310. error(EXIT_BADSC, "Stat name should be NULL - is %p\n",
  311. pstat->pwcsName);
  312. }
  313. else if (olecscmp(pstat->pwcsName, ptcsName))
  314. error(EXIT_BADSC, "Stat name mismatch - has '%s' vs. '%s'\n",
  315. OlecsOut(pstat->pwcsName), OlecsOut(ptcsName));
  316. if (pstat->type != type)
  317. error(EXIT_BADSC, "Stat type mismatch - has %lu vs. %lu\n",
  318. pstat->type, type);
  319. if (pstat->grfMode != grfMode)
  320. error(EXIT_BADSC, "Stat mode mismatch - has 0x%lX vs. 0x%lX\n",
  321. pstat->grfMode, grfMode);
  322. }
  323. // Checks on a file's existence
  324. BOOL Exists(OLECHAR* ocsFile)
  325. {
  326. char pszFile[_MAX_PATH];
  327. TTOS(ocsFile, pszFile, _tcslen(ocsFile)+1);
  328. FILE *f=fopen(pszFile, "r");
  329. BOOL fExists= (f!=NULL);
  330. if (f!=NULL) fclose(f);
  331. return (fExists);
  332. }
  333. // Gets a file's length
  334. ULONG Length(OLECHAR *ocsFile)
  335. {
  336. ULONG cb;
  337. char pszFile[_MAX_PATH];
  338. TTOS(ocsFile, pszFile, _tcslen(ocsFile)+1);
  339. FILE *f=fopen(pszFile, "r");
  340. if (!f)
  341. error(EXIT_BADSC, "Length: Unable to open '%s'\n", pszFile);
  342. int rcode=fseek(f, 0, SEEK_END);
  343. if (rcode!=0)
  344. error(EXIT_BADSC, "Length: Unable to get length for '%s'\n",
  345. pszFile);
  346. cb= (ULONG) ftell(f);
  347. fclose(f);
  348. return cb;
  349. }
  350. // Equality for FILETIME
  351. BOOL IsEqualTime(FILETIME ttTime, FILETIME ttCheck)
  352. {
  353. #ifdef _UNIX
  354. #ifdef LONGLONG
  355. #error "LONGLONG should not be defined"
  356. #else
  357. #define LONGLONG time_t
  358. #endif
  359. #endif
  360. // File times can be off by as much as 2 seconds due to FAT rounding
  361. LONGLONG tmTime = *(LONGLONG *)&ttTime;
  362. LONGLONG tmCheck = *(LONGLONG *)&ttCheck;
  363. LONGLONG tmDelta = tmTime - tmCheck;
  364. #ifdef _UNIX
  365. #undef LONGLONG
  366. #endif
  367. #ifndef _UNIX
  368. return tmDelta < 20000000i64 && tmDelta > -2i64 ;
  369. #else
  370. return tmDelta < 2; // time_t is in seconds
  371. #endif
  372. }
  373. // Get a fully qualified path for a file name
  374. void GetFullPath(TCHAR *ocsFile, TCHAR *ocsPath, int len)
  375. {
  376. char pszPath[_MAX_PATH+1], pszFile[_MAX_PATH+1];
  377. TTOS(ocsFile, pszFile, _tcslen(ocsFile)+1);
  378. _fullpath(pszPath, pszFile, len);
  379. STOT(pszPath, ocsPath, strlen(pszPath)+1);
  380. }
  381. // Memory helper functions
  382. HRESULT drtMemAlloc(ULONG ulcb, void **ppv)
  383. {
  384. HRESULT hr;
  385. IMalloc *pMalloc = NULL;
  386. if (SUCCEEDED(DfGetScode(hr = CoGetMalloc(MEMCTX_TASK, &pMalloc))))
  387. {
  388. *ppv = pMalloc->Alloc(ulcb);
  389. pMalloc->Release();
  390. if (*ppv == NULL)
  391. return ResultFromScode(E_OUTOFMEMORY);
  392. }
  393. return hr;
  394. }
  395. void drtMemFree(void *pv)
  396. {
  397. IMalloc FAR* pMalloc;
  398. if (SUCCEEDED(GetScode(CoGetMalloc(MEMCTX_TASK, &pMalloc))))
  399. {
  400. pMalloc->Free(pv);
  401. pMalloc->Release();
  402. }
  403. }
  404. #ifdef _MSC_VER
  405. #pragma pack(1)
  406. #endif
  407. struct SplitGuid
  408. {
  409. DWORD dw1;
  410. WORD w1;
  411. WORD w2;
  412. BYTE b[8];
  413. };
  414. #ifdef _MSC_VER
  415. #pragma pack()
  416. #endif
  417. char *GuidText(GUID const *pguid)
  418. {
  419. static char buf[39];
  420. SplitGuid *psg = (SplitGuid *)pguid;
  421. sprintf(buf, "{%08lX-%04hX-%04hX-%02X%02X-%02X%02X%02X%02X%02X%02X}",
  422. psg->dw1, psg->w1, psg->w2, psg->b[0], psg->b[1], psg->b[2],
  423. psg->b[3], psg->b[4], psg->b[5], psg->b[6], psg->b[7]);
  424. return buf;
  425. }