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.

615 lines
19 KiB

  1. //+============================================================================
  2. //
  3. // File: PrpSetup.cxx
  4. //
  5. // Purpose: This file builds to an executable which installs the
  6. // IProp DLL in the System(32) directory. This is provided
  7. // for the use of applications which re-distribute that DLL.
  8. //
  9. // Usage: PrpSetup [/u] [/c]
  10. //
  11. // The /u option indicates that an un-install should be performed.
  12. // The /c option indicates that console output is desired.
  13. //
  14. // History: 10/30/96 MikeHill Get "iprop.dl_" from the exe's resources.
  15. //
  16. //+============================================================================
  17. // --------
  18. // Includes
  19. // --------
  20. #include <windows.h>
  21. #include <ole2.h>
  22. #include <tchar.h>
  23. #include <stdio.h>
  24. // -------------
  25. // Global values
  26. // -------------
  27. // Name-related information for the DLL
  28. const LPTSTR tszResourceType = TEXT( "FILE" ); // Resource type
  29. const LPTSTR tszCompressedFilename = TEXT( "IPROP.DL_" ); // Temp file name
  30. const LPTSTR tszTargetFilename = TEXT( "IPROP.DLL" ); // Final file name
  31. // The reg key where we keep the DLL's install ref-count.
  32. const LPTSTR tszRegSharedDLLs
  33. = TEXT( "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\SharedDLLs" );
  34. // Registration functions in IProp DLL.
  35. const LPTSTR tszRegistrationFunction = TEXT( "DllRegisterServer" );
  36. const LPTSTR tszUnregistrationFunction = TEXT( "DllUnregisterServer" );
  37. // ------------
  38. // Return Codes
  39. // ------------
  40. #define RETURN_SUCCESS 0
  41. #define RETURN_ARGUMENT_ERROR 1
  42. #define RETURN_COULDNT_CREATE_TEMP_FILE 2
  43. #define RETURN_COULDNT_INSTALL_DLL 3
  44. #define RETURN_COULDNT_DELETE_DLL 4
  45. #define RETURN_COULDNT_REGISTER_DLL 5
  46. #define RETURN_COULDNT_ACCESS_REGISTRY 6
  47. #define RETURN_OUT_OF_MEMORY 7
  48. #define RETURN_INTERNAL_ERROR 8
  49. //+----------------------------------------------------------------------------
  50. //
  51. // Function: Register
  52. //
  53. // Synopsis: This function registers or de-registers the IProp DLL.
  54. //
  55. // Inputs: [BOOL] fUninstall (in)
  56. // If true, call DllUnregisterServer, otherwise call
  57. // DllRegisterServer
  58. //
  59. // Returns: [HRESULT]
  60. //
  61. //+----------------------------------------------------------------------------
  62. HRESULT Register( BOOL fUninstall )
  63. {
  64. HRESULT hr;
  65. HINSTANCE hinst = NULL;
  66. // A function pointer for the registration function
  67. typedef HRESULT (STDAPICALLTYPE FNREGISTRATION)();
  68. FNREGISTRATION *pfnRegistration = NULL;
  69. // Load the DLL
  70. hinst = LoadLibrary( tszTargetFilename );
  71. if( NULL == hinst )
  72. {
  73. hr = HRESULT_FROM_WIN32( GetLastError() );
  74. goto Exit;
  75. }
  76. // Get the registration function
  77. pfnRegistration = (FNREGISTRATION*)
  78. GetProcAddress( hinst,
  79. fUninstall ? tszUnregistrationFunction
  80. : tszRegistrationFunction );
  81. if( NULL == pfnRegistration )
  82. {
  83. hr = HRESULT_FROM_WIN32( GetLastError() );
  84. goto Exit;
  85. }
  86. // Register or De-register IProp.
  87. hr = (*pfnRegistration)();
  88. if( FAILED(hr) ) goto Exit;
  89. // ----
  90. // Exit
  91. // ----
  92. Exit:
  93. if( NULL != hinst )
  94. FreeLibrary( hinst );
  95. return( hr );
  96. }
  97. //+----------------------------------------------------------------------------
  98. //
  99. // Function: main()
  100. //
  101. // Synopsis: This program loads/removes IProp.DLL into/from the
  102. // System directory. A ref-count of the number of installs
  103. // of this DLL is kept in the Registry. The DLL is
  104. // also registered/deregistered.
  105. //
  106. //+----------------------------------------------------------------------------
  107. HRESULT __cdecl main(int argc, char **argv)
  108. {
  109. // File names and paths
  110. TCHAR tszSystemPath[_MAX_PATH+1]; // Path to System(32) directory
  111. TCHAR tszTempFilename[_MAX_PATH+1]; // Used by VerInstallFile()
  112. UINT cbTempFilename = sizeof( tszTempFilename ) - sizeof(TCHAR);
  113. TCHAR tszTargetPathAndFile[_MAX_PATH+1]; // E.g. "C:\Win\System32\IProp.dll"
  114. TCHAR tszTempPath[_MAX_PATH+1]; // E.g. "C:\Temp\"
  115. // E.g. "C:\Temp\iprop.dl_"
  116. TCHAR tszTempPathAndFile[_MAX_PATH+1] = {""};
  117. // Index into argv
  118. int nArgIndex;
  119. // User-settable flags.
  120. BOOL fConsole = FALSE;
  121. BOOL fInstall = FALSE;
  122. BOOL fUninstall = FALSE;
  123. // Registry data
  124. HKEY hkey;
  125. DWORD dwRegValueType;
  126. DWORD dwRefCount;
  127. DWORD cbRefCountSize = sizeof( dwRefCount );
  128. DWORD dwDisposition;
  129. // Handles for reading "iprop.dl_" out of the resources
  130. HRSRC hrsrcIProp = NULL; // Handle to the "iprop.dl_" resource.
  131. HGLOBAL hglobIProp = NULL; // Handle to the "iprop.dl_" data.
  132. LPVOID lpvIProp = NULL; // Pointer to the "iprop.dl_" data.
  133. HMODULE hmodCurrent = NULL; // Our module handle
  134. HANDLE hfileIProp = NULL; // Handle to "%TEMP%\iprop.dl_" file
  135. // Misc.
  136. HRESULT hr = S_OK;
  137. INT nReturnCode = RETURN_INTERNAL_ERROR;
  138. // -----------------
  139. // Process the Input
  140. // -----------------
  141. for( nArgIndex = 1; nArgIndex < argc; nArgIndex++ )
  142. {
  143. if( // Is this argument an option?
  144. ( argv[nArgIndex][0] == '/'
  145. ||
  146. argv[nArgIndex][0] == '-'
  147. )
  148. && // and is it more than one character?
  149. argv[nArgIndex][1] != '\0'
  150. && // and is it exactly two characters?
  151. argv[nArgIndex][2] == '\0'
  152. )
  153. {
  154. // See if it's an argument we recognize.
  155. switch( argv[nArgIndex][1] )
  156. {
  157. // Installation
  158. case 'i':
  159. case 'I':
  160. fInstall = TRUE;
  161. break;
  162. // Uninstall
  163. case 'u':
  164. case 'U':
  165. fUninstall = TRUE;
  166. break;
  167. // Console output
  168. case 'c':
  169. case 'C':
  170. fConsole = TRUE;
  171. break;
  172. }
  173. } // if( ( argv[nArgIndex][0] == '/' ...
  174. } // for( nArgIndex = 1; nArgIndex < argc; nArgIndex++ )
  175. // Did we get an illegal command-line combination?
  176. if( fInstall && fUninstall )
  177. {
  178. nReturnCode = RETURN_ARGUMENT_ERROR;
  179. goto Exit;
  180. }
  181. // Did the user fail to tell us what to do? If so,
  182. // display usage information.
  183. if( !fInstall && !fUninstall )
  184. {
  185. _tprintf( TEXT("\n") );
  186. _tprintf( TEXT(" Installation program for the Microsoft OLE Property Set Implementation\n") );
  187. _tprintf( TEXT(" Usage: IProp [/i | /u] [/c]\n") );
  188. _tprintf( TEXT(" Options: /i => Install\n")
  189. TEXT(" /u => Uninstall\n")
  190. TEXT(" /c => Console output\n") );
  191. _tprintf( TEXT(" Examples: IProp /i\n")
  192. TEXT(" IProp /u /c\n") );
  193. nReturnCode = RETURN_SUCCESS;
  194. goto Exit;
  195. }
  196. // ----------
  197. // Initialize
  198. // ----------
  199. // Find the target installation directory.
  200. if( GetSystemDirectory( tszSystemPath,
  201. sizeof(tszSystemPath) - sizeof(TCHAR))
  202. == 0 )
  203. {
  204. hr = HRESULT_FROM_WIN32( GetLastError() );
  205. nReturnCode = RETURN_COULDNT_INSTALL_DLL;
  206. goto Exit;
  207. }
  208. // Determine the target's total path & filename.
  209. _tcscpy( tszTargetPathAndFile, tszSystemPath );
  210. _tcscat( tszTargetPathAndFile, TEXT("\\") );
  211. _tcscat( tszTargetPathAndFile, tszTargetFilename );
  212. // Generate the filename we'll use for the compressed
  213. // IProp DLL file ("iprop.dl_"); get the temp directory
  214. // and post-pend a filename to it.
  215. if( !GetTempPath( sizeof(tszTempPath), tszTempPath ))
  216. {
  217. hr = HRESULT_FROM_WIN32( GetLastError() );
  218. nReturnCode = RETURN_COULDNT_CREATE_TEMP_FILE;
  219. goto Exit;
  220. }
  221. _tcscpy( tszTempPathAndFile, tszTempPath );
  222. _tcscat( tszTempPathAndFile, tszCompressedFilename );
  223. // Open the registry key that holds this DLL's ref-count.
  224. hr = RegCreateKeyEx( HKEY_LOCAL_MACHINE, // Open key
  225. tszRegSharedDLLs, // Name of subkey
  226. 0L, // Reserved
  227. NULL, // Class
  228. 0, // Options
  229. KEY_ALL_ACCESS, // SAM desired
  230. NULL, // Security attributes
  231. &hkey, // Result
  232. &dwDisposition ); // "Created" or "Opened"
  233. if( ERROR_SUCCESS != hr )
  234. {
  235. hr = HRESULT_FROM_WIN32( hr );
  236. nReturnCode = RETURN_COULDNT_ACCESS_REGISTRY;
  237. goto Exit;
  238. }
  239. // Attempt to read our ref-count
  240. hr = RegQueryValueEx( hkey, // Open key
  241. tszTargetPathAndFile, // Value name
  242. NULL, // Reserved
  243. &dwRegValueType, // Out: value type
  244. (LPBYTE) &dwRefCount, // Out: value
  245. &cbRefCountSize ); // In: buf size, out: data size
  246. if( ERROR_FILE_NOT_FOUND == hr )
  247. // This entry didn't already exist.
  248. dwRefCount = 0;
  249. else if( ERROR_SUCCESS != hr )
  250. {
  251. // There was a real error during the Query attempt.
  252. hr = HRESULT_FROM_WIN32(hr);
  253. nReturnCode = RETURN_COULDNT_ACCESS_REGISTRY;
  254. goto Exit;
  255. }
  256. else if ( REG_DWORD != dwRegValueType )
  257. {
  258. // This is an invalid entry. We won't abort, we'll just
  259. // re-initialize it to zero, and at the end we'll overwrite
  260. // whatever was already there.
  261. dwRefCount = 0;
  262. }
  263. if( fConsole )
  264. {
  265. if( fUninstall )
  266. _tprintf ( TEXT("Uninstalling \"%s\"\n"), tszTargetPathAndFile );
  267. else
  268. _tprintf( TEXT("Installing \"%s\"\n"), tszTargetPathAndFile );
  269. }
  270. // ------------------------------
  271. // Installation or Uninstallation
  272. // ------------------------------
  273. if( fUninstall )
  274. { // We're doing an Un-Install
  275. // Should we actually delete it? We haven't done a dec-ref yet,
  276. // so in the normal case, on the last delete, the RefCount will
  277. // currently be 1.
  278. if( dwRefCount <= 1 )
  279. {
  280. // Yes - we need to do a delete. First unregister the IProp
  281. // DLL. If there's an error we'll abort. So we might leave
  282. // an unused file on the machine, but that's better than
  283. // possibly deleting a file that is still in use by another
  284. // app.
  285. hr = Register( fUninstall );
  286. if( FAILED(hr) )
  287. {
  288. nReturnCode = RETURN_COULDNT_REGISTER_DLL;
  289. goto Exit;
  290. }
  291. // And delete the file
  292. if( !DeleteFile( tszTargetPathAndFile )
  293. &&
  294. ERROR_FILE_NOT_FOUND != GetLastError() )
  295. {
  296. hr = HRESULT_FROM_WIN32( GetLastError() );
  297. nReturnCode = RETURN_COULDNT_DELETE_DLL;
  298. goto Exit;
  299. }
  300. if( fConsole )
  301. _tprintf( TEXT("Removed IProp.DLL\n") );
  302. // Zero-out the ref count. We'll delete it from the
  303. // registry later
  304. dwRefCount = 0;
  305. }
  306. else
  307. {
  308. // We don't need to delete it, just dec-ref it.
  309. dwRefCount--;
  310. if( fConsole )
  311. _tprintf( TEXT("IProp.DLL not removed (reference count is now %d)\n"), dwRefCount );
  312. }
  313. } // if( fUninstall )
  314. else
  315. { // We're doing an Install
  316. DWORD dwSize; // Size of "iprop.dl_".
  317. DWORD cbWritten = 0;
  318. if( fConsole )
  319. _tprintf( TEXT("Extracting \"%s\"\n"), tszTempPathAndFile );
  320. // Get our module handle;
  321. hmodCurrent = GetModuleHandle( NULL );
  322. if( NULL == hmodCurrent )
  323. {
  324. hr = HRESULT_FROM_WIN32( GetLastError() );
  325. nReturnCode = RETURN_OUT_OF_MEMORY;
  326. goto Exit;
  327. }
  328. // Get the resource which is actually the compressed IProp DLL
  329. hrsrcIProp = FindResource( hmodCurrent,
  330. tszCompressedFilename,
  331. tszResourceType );
  332. if( NULL == hrsrcIProp )
  333. {
  334. hr = HRESULT_FROM_WIN32( GetLastError() );
  335. nReturnCode = RETURN_OUT_OF_MEMORY;
  336. goto Exit;
  337. }
  338. // Get the size of "iprop.dl_"
  339. dwSize = SizeofResource( hmodCurrent, hrsrcIProp );
  340. if( 0 == dwSize )
  341. {
  342. hr = HRESULT_FROM_WIN32( GetLastError() );
  343. nReturnCode = RETURN_OUT_OF_MEMORY;
  344. goto Exit;
  345. }
  346. // Get "iprop.dl_" into a memory buffer.
  347. hglobIProp = LoadResource( hmodCurrent, hrsrcIProp );
  348. if( NULL == hglobIProp )
  349. {
  350. hr = HRESULT_FROM_WIN32( GetLastError() );
  351. nReturnCode = RETURN_OUT_OF_MEMORY;
  352. goto Exit;
  353. }
  354. // Get a pointer to the "iprop.dl_" data.
  355. lpvIProp = LockResource( hglobIProp );
  356. if( NULL == lpvIProp )
  357. {
  358. hr = HRESULT_FROM_WIN32( GetLastError() );
  359. nReturnCode = RETURN_OUT_OF_MEMORY;
  360. goto Exit;
  361. }
  362. // Create a temporary file, which will be "iprop.dl_"
  363. hfileIProp = CreateFile(
  364. tszTempPathAndFile, // E.g. "C:\Temp\iprop.dl_"
  365. GENERIC_READ | GENERIC_WRITE, // Requested access
  366. FILE_SHARE_READ, // Sharing mode
  367. NULL, // No security attributes
  368. CREATE_ALWAYS, // Overwrite existing
  369. FILE_ATTRIBUTE_NORMAL, // Default attributes
  370. NULL ); // No template file
  371. if( INVALID_HANDLE_VALUE == hfileIProp )
  372. {
  373. hr = HRESULT_FROM_WIN32( GetLastError() );
  374. nReturnCode = RETURN_COULDNT_CREATE_TEMP_FILE;
  375. goto Exit;
  376. }
  377. // Write the contents of "iprop.dl_"
  378. if( !WriteFile( hfileIProp, lpvIProp, dwSize, &cbWritten, NULL ))
  379. {
  380. hr = HRESULT_FROM_WIN32( GetLastError() );
  381. nReturnCode = RETURN_COULDNT_CREATE_TEMP_FILE;
  382. goto Exit;
  383. }
  384. // We must close the file, or VerInstallFile won't open it.
  385. CloseHandle( hfileIProp );
  386. hfileIProp = NULL;
  387. // Install the file.
  388. hr = VerInstallFile( 0, // Flags
  389. tszCompressedFilename, // Source filename
  390. tszTargetFilename, // Dest filename
  391. tszTempPath, // Source location
  392. tszSystemPath, // Target location
  393. tszSystemPath, // Location of old version
  394. tszTempFilename, // Out: name of temp file
  395. &cbTempFilename); // In: size of buf, Out: name
  396. // If VerInstallFile left a temporary file, delete it now.
  397. if( hr & VIF_TEMPFILE )
  398. {
  399. TCHAR tszDeleteTempFile[_MAX_PATH+1];
  400. _tcscpy( tszDeleteTempFile, tszSystemPath );
  401. _tcscat( tszDeleteTempFile, TEXT("\\") );
  402. _tcscat( tszDeleteTempFile, tszTempFilename );
  403. DeleteFile( tszDeleteTempFile );
  404. }
  405. // If the file was installed successfully, register it.
  406. if( 0 == hr )
  407. {
  408. hr = Register( fUninstall );
  409. if( FAILED(hr) )
  410. {
  411. nReturnCode = RETURN_COULDNT_REGISTER_DLL;
  412. goto Exit;
  413. }
  414. }
  415. // If the error wasn't "newer version exists", then we
  416. // have a fatal error.
  417. else if( 0 == (hr & VIF_SRCOLD) )
  418. {
  419. nReturnCode = RETURN_COULDNT_INSTALL_DLL;
  420. goto Exit;
  421. }
  422. else if( fConsole )
  423. {
  424. _tprintf( TEXT("A newer version of the file is already installed\n") );
  425. }
  426. // Do an add-ref.
  427. dwRefCount++;
  428. } // if( fUninstall ) ... else
  429. // ------------------
  430. // Save the Ref-Count
  431. // ------------------
  432. // Did we actually delete the DLL?
  433. if( 0 == dwRefCount )
  434. {
  435. // Delete our entry from the SharedDlls entry
  436. hr = RegDeleteValue( hkey, tszTargetPathAndFile );
  437. if( ERROR_FILE_NOT_FOUND == hr )
  438. hr = ERROR_SUCCESS;
  439. else if( ERROR_SUCCESS != hr )
  440. {
  441. hr = HRESULT_FROM_WIN32(hr);
  442. nReturnCode = RETURN_COULDNT_ACCESS_REGISTRY;
  443. goto Exit;
  444. }
  445. }
  446. else
  447. {
  448. // Otherwise, put the new ref-count in the registry.
  449. hr = RegSetValueEx( hkey, // Open key
  450. tszTargetPathAndFile, // Value name
  451. 0, // Reserved
  452. REG_DWORD, // Value type
  453. (LPBYTE) &dwRefCount, // Value buffer
  454. sizeof( dwRefCount )); // Size of value
  455. if( ERROR_SUCCESS != hr )
  456. {
  457. hr = HRESULT_FROM_WIN32(hr);
  458. nReturnCode = RETURN_COULDNT_ACCESS_REGISTRY;
  459. goto Exit;
  460. }
  461. } // if( 0 == dwRefCount ) ... else
  462. // ----
  463. // Exit
  464. // ----
  465. Exit:
  466. if( fConsole )
  467. {
  468. // We only succeeded if hr is 0; VerInstallFile might return
  469. // a bitmapped error that doesn't look like an HRESULT error
  470. // code.
  471. if( 0 == hr )
  472. _tprintf( TEXT("%s successful\n"),
  473. fUninstall ? TEXT("Uninstall") : TEXT("Install") );
  474. else
  475. _tprintf( TEXT("%s failed. Return code = %d (%08X)\n"),
  476. nReturnCode,
  477. fUninstall ? TEXT("Uninstall") : TEXT("Install"),
  478. hr );
  479. }
  480. // Remove the temporary file (we initialized this to "", so this
  481. // call should always return success or file-not-found).
  482. DeleteFile( tszTempPathAndFile );
  483. // Free all the handles we've used.
  484. if( hfileIProp ) CloseHandle( hfileIProp );
  485. if( lpvIProp ) GlobalUnlock( lpvIProp );
  486. return( nReturnCode );
  487. }