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.

449 lines
12 KiB

  1. //+===============================================================
  2. //
  3. // File: CFMEx.cxx
  4. //
  5. // Purpose: This file provides the main() and global functions
  6. // for the CreateFileMonikerEx (CFMEx) DRT.
  7. // This DRT tests the CreateFileMonikerEx API (new to
  8. // Cairo), as well as related changes to BIND_OPTS
  9. // (use of the BIND_OPTS2 structure).
  10. //
  11. // All moniker activity is performed in the CMoniker
  12. // object (such as creating a bind context, creating
  13. // a link source file, moving it, binding it, etc.).
  14. //
  15. // The test engine is in the CTest object. When a link
  16. // source file is moved to test link-tracking, the
  17. // original and final location of the file may be
  18. // specified by the user (on the command-line). CTest
  19. // is aware of the filesystem type (FAT, NTFS, OFS)
  20. // of these locations, and is aware of how that will
  21. // effect the results.
  22. //
  23. // This file also provides global functions (not associated
  24. // with an object).
  25. //
  26. // Usage: cfmex [-o<Directory>] [-f<Directory>]
  27. //
  28. // -o<Directory> specifies the original directory for link sources
  29. // -f<Directory> specifies the final directory for link sources
  30. //
  31. // Examples: cfmex
  32. // cfmex -oC:\ -fC:\
  33. //
  34. //+===============================================================
  35. // ----
  36. // TODO:
  37. // ----
  38. //
  39. // - Replace CRT calls with Win32 calls.
  40. // - Validate the directory in CDirectory.
  41. // - Add a flag to CDirectory to indicate "indexed".
  42. // - Add a flag to CDirectory to indicate local vs remote.
  43. // - Add a test to verify that the moniker returned from Reduce is
  44. // not a tracking moniker.
  45. //
  46. // -------------
  47. // Include Files
  48. // -------------
  49. #define _DCOM_ // Allow DCOM extensions (e.g., CoInitializeEx).
  50. #include <windows.h>
  51. #include <stdlib.h>
  52. #include <stdio.h>
  53. #include <wchar.h>
  54. #include <wtypes.h>
  55. #include <oaidl.h>
  56. #include <dsys.h>
  57. #include <olecairo.h>
  58. #include "CFMEx.hxx"
  59. #include "CMoniker.hxx"
  60. #include "CTest.hxx"
  61. #include "CDir.hxx"
  62. // ------
  63. // Macros
  64. // ------
  65. // Early-exit macro: put the error message in a global array,
  66. // and jump to Exit
  67. WCHAR wszErrorMessage[ 512 ];
  68. #undef EXIT
  69. #define EXIT( error ) \
  70. {\
  71. wcscpy( wszErrorMessage, ##error );\
  72. goto Exit;\
  73. }
  74. // Run a Test: Display a new paragraph on the screen, run a test,
  75. // and update stats.
  76. #define RUN_TEST( testID ) \
  77. {\
  78. nTotalTests++; \
  79. wprintf( L"----------------------------------------------\n" ); \
  80. wprintf( L"Test %d: ", nTotalTests ); \
  81. if( cTest.##testID ) \
  82. wprintf( L"Passed\n" ); \
  83. else \
  84. nTestsFailed++; \
  85. }
  86. //+---------------------------------------------------------------------------------------
  87. //
  88. // Function: DisplayHelp
  89. //
  90. // Synopsis: Display a help screen with usage information.
  91. //
  92. // Inputs: None.
  93. //
  94. // Outputs: None.
  95. //
  96. // Effects: None
  97. //
  98. //+---------------------------------------------------------------------------------------
  99. void DisplayHelp( void )
  100. {
  101. wprintf( L"This DRT tests the CreateFileMonikerEx API, and related changes.\n"
  102. L"Most of these tests create a link source file, create a moniker\n"
  103. L"representing that file, then move the file. You can specify the\n"
  104. L"original and/or final locations of the link source, or let those\n"
  105. L"locations default to the \%TEMP\% directory\n"
  106. L"\n"
  107. L"Usage: cfmex [-o<Directory>] [-f<Directory>]\n"
  108. L"\n"
  109. L"Where: -o<Directory> specifies the original directory for link sources\n"
  110. L" -f<Directory> specifies the final directory for link sources\n"
  111. L"\n"
  112. L"Note: If an original or final directory is specified on the command-\n"
  113. L" line, that directory must already exist. If one of these locations\n"
  114. L" is not specified, the TEMP environment variable must be defined\n"
  115. L" and it must specify an extant directory.\n"
  116. L"\n"
  117. L"E.g.: cfmex\n"
  118. L" cfmex -oC:\\\n"
  119. L" cfmex -oE:\\ -fF:\\temp\n"
  120. L"\n" );
  121. return;
  122. }
  123. //+---------------------------------------------------------------------------------------
  124. //
  125. // Function: UnicodeToAnsi
  126. //
  127. // Synopsis: Convert a Unicode (wide) string to ANSI
  128. //
  129. // Inputs: The Unicode String
  130. // The buffer for the ANSI string
  131. // The size of the above buffer
  132. //
  133. // Outputs: 0 if successful
  134. // GetLastError() otherwise
  135. //
  136. // Effects: None
  137. //
  138. //+---------------------------------------------------------------------------------------
  139. DWORD UnicodeToAnsi( const WCHAR * wszUnicode,
  140. CHAR * szAnsi,
  141. int cbAnsiMax )
  142. {
  143. int cbAnsi = 0;
  144. // Convert WCS to the MBCS, using the ANSI code page.
  145. cbAnsi = WideCharToMultiByte( CP_ACP,
  146. WC_COMPOSITECHECK | WC_DEFAULTCHAR,
  147. wszUnicode,
  148. wcslen( wszUnicode ),
  149. szAnsi,
  150. cbAnsiMax,
  151. NULL,
  152. NULL );
  153. if( !cbAnsi )
  154. {
  155. // No characters were converted - there was an error.
  156. // Note that this will be returned if a null Unicode string is
  157. // passed in.
  158. return( GetLastError() );
  159. }
  160. else
  161. {
  162. // Terminate the Ansi string and return.
  163. szAnsi[ cbAnsi ] = '\0';
  164. return( 0L );
  165. }
  166. } // UnicodeToAnsi()
  167. //+---------------------------------------------------------------------------------------
  168. //
  169. // Function: AnsiToUnicode
  170. //
  171. // Synopsis: Convert an ANSI string to Unicode (i.e. Wide)
  172. //
  173. // Inputs: The ANSI String
  174. // The buffer for the Unicode string
  175. // The size of the above buffer.
  176. //
  177. // Outputs: 0 if successful
  178. // GetLastError() otherwise
  179. //
  180. // Effects: None
  181. //
  182. //+---------------------------------------------------------------------------------------
  183. DWORD AnsiToUnicode( const CHAR * szAnsi,
  184. WCHAR * wszUnicode,
  185. int cbUnicodeMax )
  186. {
  187. int cbUnicode = 0;
  188. cbUnicode = MultiByteToWideChar( CP_ACP,
  189. MB_PRECOMPOSED,
  190. szAnsi,
  191. strlen( szAnsi ),
  192. wszUnicode,
  193. cbUnicodeMax );
  194. if( !cbUnicode )
  195. {
  196. // If no characters were converted, then there was an error.
  197. return( GetLastError() );
  198. }
  199. else
  200. {
  201. // Terminate the Unicode string and return.
  202. wszUnicode[ cbUnicode ] = L'\0';
  203. return( 0L );
  204. }
  205. } // AnsiToUnicode()
  206. //+---------------------------------------------------------------------------------------
  207. //
  208. // Function: main
  209. //
  210. // Synopsis: Run the CFMEx DRT. All tests are in the CTest object. These
  211. // tests are simply called sequentially.
  212. //
  213. // Inputs: (argc) the count of arguments
  214. // (argv) the arguments. See DisplayHelp() for a description.
  215. //
  216. // Outputs: 0 if completely successful
  217. // 1 if help was displayed
  218. // 2 if a test failed
  219. //
  220. // Effects: None
  221. //
  222. //+---------------------------------------------------------------------------------------
  223. int main( int argc, char** argv )
  224. {
  225. // ---------------
  226. // Local Variables
  227. // ---------------
  228. // Test statistics.
  229. int nTotalTests = 0;
  230. int nTestsFailed = 0;
  231. // The original and final directories (in ANSI) of the link source file.
  232. CHAR* szOriginalDirectory = NULL;
  233. CHAR* szFinalDirectory = NULL;
  234. // Objects representing the original and final directories.
  235. CDirectory cDirectoryOriginal;
  236. CDirectory cDirectoryFinal;
  237. // The test engine.
  238. CTest cTest;
  239. int index = 0;
  240. // --------------
  241. // Opening Banner
  242. // --------------
  243. printf( "\n"
  244. "*** CreateFileMonikerEx DRT ***\n"
  245. "(use \"cfmex -?\" for help)\n"
  246. "\n" );
  247. // ------------------------------
  248. // Handle command-line parameters
  249. // ------------------------------
  250. for( index = 1; index < argc; index++ )
  251. {
  252. // The first character of an argument should be an "-" or "/"
  253. // (they are interchangable).
  254. if( ( ( argv[index][0] != '-' )
  255. &&
  256. ( argv[index][0] != '/' )
  257. )
  258. ||
  259. ( strlen( &argv[index][0] ) < 2 ) // Must have more than '-' & an option.
  260. )
  261. {
  262. printf( "Invalid argument ignored: %s\n", argv[ index ] );
  263. continue;
  264. }
  265. // Switch based on the first character (which defines the option).
  266. switch( argv[index][1] )
  267. {
  268. // Help requested
  269. case '?':
  270. DisplayHelp();
  271. exit( 1 );
  272. // An original directory is specified.
  273. case 'o':
  274. case 'O':
  275. // Verify the specified path length.
  276. if( strlen( &argv[index][2] ) > MAX_PATH )
  277. {
  278. printf( "Path is too long, ignored: %s\n", &argv[index][2] );
  279. break; // From the switch
  280. }
  281. szOriginalDirectory = &argv[index][2];
  282. break; // From the switch
  283. // A final directory is specified
  284. case 'f':
  285. case 'F':
  286. if( strlen( &argv[index][2] ) > MAX_PATH )
  287. {
  288. printf( "Path is too long, ignored: %s\n", &argv[index][2] );
  289. break; // From the switch
  290. }
  291. szFinalDirectory = &argv[index][2];
  292. break; // From the switch
  293. // Invalid argument.
  294. default:
  295. printf( "Invalid option ignored: \"-%c\"\n", argv[index][1] );
  296. break;
  297. }
  298. }
  299. // --------------
  300. // Initialization
  301. // --------------
  302. // Initialize COM
  303. CoInitialize( NULL );
  304. // Initialize the CDirectory and CTest objects. If no original/final
  305. // directory was specified above, CDirectory will create a default
  306. // (based on %TEMP%).
  307. if( !cDirectoryOriginal.Initialize( szOriginalDirectory ) )
  308. EXIT( L"Could not initialize cDirectoryOriginal" );
  309. if( !cDirectoryFinal.Initialize( szFinalDirectory ) )
  310. EXIT( L"Could not initialize cDirectoryFinal" );
  311. if( !cTest.Initialize( cDirectoryOriginal, cDirectoryFinal ) )
  312. EXIT( L"Could not initialize CTest" );
  313. // Show the end result.
  314. wprintf( L"Link sources will be created in \"%s\" (%s)\n",
  315. cDirectoryOriginal.GetDirectoryName(),
  316. cDirectoryOriginal.GetFileSystemName() );
  317. wprintf( L"and will be moved to \"%s\" (%s)\n",
  318. cDirectoryFinal.GetDirectoryName(),
  319. cDirectoryFinal.GetFileSystemName() );
  320. // ---------
  321. // Run Tests
  322. // ---------
  323. RUN_TEST( GetOversizedBindOpts() );
  324. RUN_TEST( GetUndersizedBindOpts() );
  325. RUN_TEST( SetOversizedBindOpts() );
  326. RUN_TEST( SetUndersizedBindOpts() );
  327. RUN_TEST( CreateFileMonikerEx() );
  328. RUN_TEST( GetDisplayName() );
  329. RUN_TEST( GetTimeOfLastChange() );
  330. RUN_TEST( ComposeWith() );
  331. RUN_TEST( IPersist() );
  332. RUN_TEST( BindToStorage() );
  333. RUN_TEST( BindToObject() );
  334. RUN_TEST( DeleteLinkSource( 0 )); // Timeout immediately.
  335. RUN_TEST( DeleteLinkSource( 200 )); // Timeout in multi-threaded search
  336. RUN_TEST( DeleteLinkSource( INFINITE )); // Don't timeout
  337. // ----
  338. // Exit
  339. // ----
  340. Exit:
  341. // Show test results.
  342. wprintf( L"\n\nTesting complete:\n"
  343. L" Total Tests = %d\n"
  344. L" Failed = %d\n",
  345. nTotalTests, nTestsFailed );
  346. // Free COM
  347. CoUninitialize();
  348. return( nTestsFailed ? 2 : 0 );
  349. }