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.

1484 lines
48 KiB

  1. /*****************************************************************************\
  2. * MODULE: IppOcm.cxx
  3. *
  4. * The module contains routines for the setting up the WWW Printer Service. The main entry point is
  5. * IppOCEntry which will be called by the Optional Component Manager.
  6. *
  7. * Copyright (C) 2002 Microsoft Corporation
  8. *
  9. \*****************************************************************************/
  10. //
  11. //
  12. // Note: We cannot use precomp.h here since we requrie ATL which can only be included in C++ source files.
  13. //
  14. //
  15. #define INITGUID // Needed to do it to get GUID_NULL defined.
  16. #include "precomp.h"
  17. #pragma hdrstop
  18. #include <iadmw.h> // Interface header
  19. #include <iiscnfg.h> // MD_ & IIS_MD_ defines
  20. #include <ocmanage.h> // OC_ defines
  21. // for adsi objects
  22. #include <Iads.h>
  23. #include <Adshlp.h>
  24. // for the IID_IISWebService object
  25. #include "iiisext.h"
  26. #include "iisext_i.c"
  27. #define MY_META_TIMEOUT 1000
  28. TCHAR const cszMimeMap[] = TEXT("MimeMap");
  29. TCHAR const cszWebPnPMap[] = TEXT(".webpnp,application/octet-stream");
  30. TCHAR const cszW3SvcRootPath[] = TEXT("/LM/W3svc/1/Root");
  31. TCHAR const cszPrinters[] = TEXT("Printers");
  32. TCHAR const cszWebSvcExtRestrictionListADSILocation[] = TEXT("IIS://LOCALHOST/W3SVC");
  33. //
  34. // Component ID for the OCM
  35. //
  36. TCHAR const cszComponentId[] = TEXT("InetPrint");
  37. TCHAR const cszExtPathFmt[] = TEXT("%ws\\msw3prt.dll");
  38. TCHAR const cszGroupId[] = TEXT("W3PRT");
  39. TCHAR const cszGroupDescription[] = TEXT("Internet Printing");
  40. TCHAR const cszASPId[] = TEXT("ASP");
  41. //
  42. // Service ID & Reg Key for the WWW Service
  43. //
  44. TCHAR const cszW3Svc[] = TEXT("w3svc");
  45. TCHAR const cszW3SvcReg[] = TEXT("System\\CurrentControlSet\\Services\\W3SVC");
  46. //
  47. // Strings to fire up the RunDll32 process
  48. //
  49. TCHAR const cszInstallInetPrint[] = TEXT("rundll32 ntprint.dll,SetupInetPrint Install");
  50. TCHAR const cszRemoveInetPrint[] = TEXT("rundll32 ntprint.dll,SetupInetPrint Remove");
  51. CHAR const cszInstall[] = "Install";
  52. CHAR const cszRemove[] = "Remove";
  53. typedef struct MySetupStruct
  54. {
  55. OCMANAGER_ROUTINES OCHelpers;
  56. SETUP_DATA OCData;
  57. BOOL bFirstCall;
  58. BOOL bInitState;
  59. } MYSETUPSTRUCT;
  60. //
  61. // Function Prototypes
  62. //
  63. HRESULT
  64. AddVirtualDir(
  65. IMSAdminBase *pIMetaBase
  66. );
  67. HRESULT
  68. AddWebExtension(
  69. VOID
  70. );
  71. HRESULT
  72. AddScriptAtPrinterVDir(
  73. IMSAdminBase *pIMetaBase
  74. );
  75. HRESULT
  76. AddMimeType(
  77. IMSAdminBase *pIMetaBase
  78. );
  79. HRESULT
  80. RemoveWebExtension(
  81. VOID
  82. );
  83. DWORD
  84. WriteStrippedScriptValue(
  85. IMSAdminBase *pIMetaBase,
  86. METADATA_HANDLE hMeta, // Handle to /LM tree
  87. PWCHAR pszScripts // MULTI_SZ string already there
  88. );
  89. DWORD
  90. WriteStrippedMimeMapValue(
  91. IMSAdminBase *pIMetaBase,
  92. METADATA_HANDLE hMeta, // Handle to /LM tree
  93. PWCHAR pszMimeMap // MULTI_SZ string already there
  94. );
  95. LPWSTR
  96. mystrstrni(
  97. LPWSTR pSrc,
  98. LPWSTR pSearch
  99. );
  100. LPWSTR
  101. IsStrInMultiSZ(
  102. LPWSTR pMultiSzSrc,
  103. LPWSTR pSearch
  104. );
  105. DWORD
  106. GetMultiSZLen(
  107. IN LPWSTR pMultiSzSrc
  108. );
  109. BOOL
  110. IsVDIRInstalled(
  111. VOID
  112. )
  113. {
  114. IMSAdminBase *pIMetaBase = NULL;
  115. BOOL bInstalled = FALSE;
  116. //
  117. // Init up the MetaBase
  118. //
  119. if ( SUCCEEDED(CoInitializeEx( NULL, COINIT_MULTITHREADED )) &&
  120. SUCCEEDED(::CoCreateInstance(CLSID_MSAdminBase,
  121. NULL,
  122. CLSCTX_ALL,
  123. IID_IMSAdminBase,
  124. (void **)&pIMetaBase)) )
  125. {
  126. WCHAR szVirPath[MAX_PATH];
  127. HRESULT hr; // com error status
  128. METADATA_HANDLE hMeta = NULL; // handle to metabase
  129. DWORD dwMDRequiredDataLen;
  130. METADATA_RECORD mr;
  131. // open key to ROOT on website #1 (default)
  132. hr = pIMetaBase->OpenKey(METADATA_MASTER_ROOT_HANDLE,
  133. cszW3SvcRootPath,
  134. METADATA_PERMISSION_READ,
  135. MY_META_TIMEOUT,
  136. &hMeta);
  137. if ( SUCCEEDED( hr ) )
  138. {
  139. mr.dwMDIdentifier = MD_VR_PATH;
  140. mr.dwMDAttributes = 0;
  141. mr.dwMDUserType = IIS_MD_UT_FILE;
  142. mr.dwMDDataType = STRING_METADATA;
  143. mr.dwMDDataLen = sizeof( szVirPath );
  144. mr.pbMDData = reinterpret_cast<unsigned char *>(szVirPath);
  145. // Read LM/W3Svc/1/Root/Printers see if MD_VR_PATH exists.
  146. hr = pIMetaBase->GetData( hMeta, cszPrinters, &mr, &dwMDRequiredDataLen );
  147. if ( SUCCEEDED(hr) )
  148. bInstalled = TRUE;
  149. //
  150. // Close the Web Server Key
  151. //
  152. pIMetaBase->CloseKey( hMeta );
  153. }
  154. pIMetaBase->Release();
  155. }
  156. CoUninitialize();
  157. return bInstalled;
  158. }
  159. DWORD
  160. InstallWebPrinting(
  161. VOID
  162. )
  163. {
  164. IMSAdminBase *pIMetaBase = NULL;
  165. BOOL bInstalled = FALSE;
  166. HRESULT hr = S_OK;
  167. DBGMSG(DBG_INFO, ("Installing Web Printing.\n"));
  168. //
  169. // Init up the MetaBase
  170. //
  171. if ( SUCCEEDED(CoInitializeEx( NULL, COINIT_MULTITHREADED )) &&
  172. SUCCEEDED(::CoCreateInstance(CLSID_MSAdminBase,
  173. NULL,
  174. CLSCTX_ALL,
  175. IID_IMSAdminBase,
  176. (void **)&pIMetaBase)) )
  177. {
  178. //
  179. // Add the Virtual Directory
  180. //
  181. hr = AddVirtualDir(pIMetaBase);
  182. if (SUCCEEDED(hr))
  183. {
  184. //
  185. // Add Inet Print to the Security Console
  186. //
  187. hr = AddWebExtension();
  188. }
  189. if (SUCCEEDED(hr))
  190. {
  191. //
  192. // Add the .printer Script Map
  193. //
  194. hr = AddScriptAtPrinterVDir(pIMetaBase);
  195. }
  196. if (SUCCEEDED(hr))
  197. {
  198. //
  199. // Add the .webpnp MimeType
  200. //
  201. hr = AddMimeType(pIMetaBase);
  202. }
  203. pIMetaBase->Release();
  204. }
  205. CoUninitialize();
  206. return HRESULT_CODE(hr);
  207. }
  208. HRESULT
  209. AddVirtualDir(
  210. IMSAdminBase *pIMetaBase
  211. )
  212. {
  213. METADATA_HANDLE hMeta = NULL; // handle to metabase
  214. WCHAR szVirPath[MAX_PATH];
  215. WCHAR szPath[MAX_PATH];
  216. DWORD dwMDRequiredDataLen;
  217. DWORD dwAccessPerm;
  218. METADATA_RECORD mr;
  219. HRESULT hr;
  220. DBGMSG(DBG_INFO, ("Adding the Virtual Dir\r\n"));
  221. // Attempt to open the virtual dir set on Web server #1 (default server)
  222. hr = pIMetaBase->OpenKey( METADATA_MASTER_ROOT_HANDLE,
  223. cszW3SvcRootPath,
  224. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
  225. MY_META_TIMEOUT,
  226. &hMeta );
  227. // Create the key if it does not exist.
  228. if ( SUCCEEDED( hr ) )
  229. {
  230. mr.dwMDIdentifier = MD_VR_PATH;
  231. mr.dwMDAttributes = 0;
  232. mr.dwMDUserType = IIS_MD_UT_FILE;
  233. mr.dwMDDataType = STRING_METADATA;
  234. mr.dwMDDataLen = sizeof( szVirPath );
  235. mr.pbMDData = reinterpret_cast<unsigned char *>(szVirPath);
  236. // Read LM/W3Svc/1/Root/Printers see if MD_VR_PATH exists.
  237. hr = pIMetaBase->GetData( hMeta, cszPrinters, &mr, &dwMDRequiredDataLen );
  238. if ( FAILED( hr ) )
  239. {
  240. if ( hr == MD_ERROR_DATA_NOT_FOUND ||
  241. HRESULT_CODE(hr) == ERROR_PATH_NOT_FOUND )
  242. {
  243. // Write both the key and the values if GetData() failed with any of the two errors.
  244. pIMetaBase->AddKey( hMeta, cszPrinters );
  245. if ( GetWindowsDirectory( szPath, sizeof(szPath) / sizeof (TCHAR)) )
  246. { // Return value is the length in chars w/o null char.
  247. DBGMSG(DBG_INFO, ("Writing our virtual dir.\n"));
  248. hr = StringCchPrintf(szVirPath, COUNTOF(szVirPath), L"%ws\\web\\printers", szPath);
  249. if ( SUCCEEDED(hr) )
  250. {
  251. mr.dwMDIdentifier = MD_VR_PATH;
  252. mr.dwMDAttributes = METADATA_INHERIT;
  253. mr.dwMDUserType = IIS_MD_UT_FILE;
  254. mr.dwMDDataType = STRING_METADATA;
  255. mr.dwMDDataLen = (wcslen(szVirPath) + 1) * sizeof(WCHAR);
  256. mr.pbMDData = reinterpret_cast<unsigned char *>(szVirPath);
  257. //
  258. // Write MD_VR_PATH value
  259. //
  260. hr = pIMetaBase->SetData( hMeta, cszPrinters, &mr );
  261. }
  262. //
  263. // Set the default authentication method
  264. //
  265. if ( SUCCEEDED(hr) )
  266. {
  267. DWORD dwAuthorization = MD_AUTH_NT; // NTLM only.
  268. mr.dwMDIdentifier = MD_AUTHORIZATION;
  269. mr.dwMDAttributes = METADATA_INHERIT; // need to inherit so that all subdirs are also protected.
  270. mr.dwMDUserType = IIS_MD_UT_FILE;
  271. mr.dwMDDataType = DWORD_METADATA;
  272. mr.dwMDDataLen = sizeof(DWORD);
  273. mr.pbMDData = reinterpret_cast<unsigned char *>(&dwAuthorization);
  274. // Write MD_AUTHORIZATION value
  275. hr = pIMetaBase->SetData( hMeta, cszPrinters, &mr );
  276. }
  277. }
  278. }
  279. }
  280. // In the following, do the stuff that we always want to do to the virtual dir, regardless of Admin's setting.
  281. if ( SUCCEEDED(hr) )
  282. {
  283. dwAccessPerm = MD_ACCESS_READ | MD_ACCESS_SCRIPT;
  284. mr.dwMDIdentifier = MD_ACCESS_PERM;
  285. mr.dwMDAttributes = METADATA_INHERIT; // Make it inheritable so all subdirectories will have the same rights.
  286. mr.dwMDUserType = IIS_MD_UT_FILE;
  287. mr.dwMDDataType = DWORD_METADATA;
  288. mr.dwMDDataLen = sizeof(DWORD);
  289. mr.pbMDData = reinterpret_cast<unsigned char *>(&dwAccessPerm);
  290. // Write MD_ACCESS_PERM value
  291. hr = pIMetaBase->SetData( hMeta, cszPrinters, &mr );
  292. }
  293. if ( SUCCEEDED(hr) )
  294. {
  295. PWCHAR szDefLoadFile = L"ipp_0001.asp";
  296. mr.dwMDIdentifier = MD_DEFAULT_LOAD_FILE;
  297. mr.dwMDAttributes = METADATA_INHERIT;
  298. mr.dwMDUserType = IIS_MD_UT_FILE;
  299. mr.dwMDDataType = STRING_METADATA;
  300. mr.dwMDDataLen = (wcslen(szDefLoadFile) + 1) * sizeof(WCHAR);
  301. mr.pbMDData = reinterpret_cast<unsigned char *>(szDefLoadFile);
  302. // Write MD_DEFAULT_LOAD_FILE value
  303. hr = pIMetaBase->SetData( hMeta, cszPrinters, &mr );
  304. }
  305. if ( SUCCEEDED(hr) )
  306. {
  307. PWCHAR szKeyType = IIS_CLASS_WEB_VDIR_W;
  308. mr.dwMDIdentifier = MD_KEY_TYPE;
  309. mr.dwMDAttributes = METADATA_NO_ATTRIBUTES;
  310. mr.dwMDUserType = IIS_MD_UT_SERVER;
  311. mr.dwMDDataType = STRING_METADATA;
  312. mr.dwMDDataLen = (wcslen(szKeyType) + 1) * sizeof(WCHAR);
  313. mr.pbMDData = reinterpret_cast<unsigned char *>(szKeyType);
  314. // Write MD_DEFAULT_LOAD_FILE value
  315. hr = pIMetaBase->SetData( hMeta, cszPrinters, &mr );
  316. }
  317. }
  318. pIMetaBase->CloseKey( hMeta );
  319. return hr;
  320. }
  321. HRESULT
  322. AddWebExtension(
  323. VOID
  324. )
  325. {
  326. WCHAR szExtPath[MAX_PATH];
  327. WCHAR szSystemPath[MAX_PATH];
  328. LPTSTR pszGroupDesc = NULL;
  329. IISWebService* pWeb = NULL;
  330. DBGMSG(DBG_INFO, ("Adding the Web Extension\r\n"));
  331. HRESULT hr = ADsGetObject(cszWebSvcExtRestrictionListADSILocation, IID_IISWebService, (void**)&pWeb);
  332. if (SUCCEEDED(hr) && NULL != pWeb)
  333. {
  334. VARIANT var1,var2;
  335. VariantInit(&var1);
  336. VariantInit(&var2);
  337. var1.vt = VT_BOOL;
  338. var1.boolVal = VARIANT_TRUE;
  339. var2.vt = VT_BOOL;
  340. var2.boolVal = VARIANT_FALSE;
  341. pszGroupDesc = GetStringFromRcFile(IDS_INTERNET_PRINTING);
  342. hr = (pszGroupDesc ? S_OK : E_FAIL);
  343. if (SUCCEEDED(hr))
  344. {
  345. hr = GetSystemDirectory(szSystemPath, COUNTOF (szSystemPath)) > 0 ? S_OK : E_FAIL;
  346. }
  347. if (SUCCEEDED(hr))
  348. {
  349. hr = StringCchPrintf(szExtPath, COUNTOF(szExtPath), cszExtPathFmt, szSystemPath);
  350. }
  351. if (SUCCEEDED(hr))
  352. {
  353. hr = pWeb->AddExtensionFile(szExtPath,var1,(LPWSTR) cszGroupId,var2,(LPWSTR) pszGroupDesc);
  354. }
  355. if (FAILED(hr))
  356. {
  357. if (ERROR_DUP_NAME == HRESULT_CODE(hr))
  358. {
  359. hr = S_OK;
  360. }
  361. else
  362. {
  363. DBGMSG(DBG_INFO, ("AddExtension failed,probably already exists\r\n"));
  364. }
  365. }
  366. VariantClear(&var1);
  367. VariantClear(&var2);
  368. }
  369. if (SUCCEEDED(hr) && NULL != pWeb)
  370. {
  371. hr = pWeb->AddDependency((LPWSTR) pszGroupDesc,(LPWSTR) cszASPId);
  372. if (FAILED(hr))
  373. {
  374. if (ERROR_DUP_NAME == HRESULT_CODE(hr))
  375. {
  376. hr = S_OK;
  377. }
  378. else
  379. {
  380. DBGMSG(DBG_INFO, ("AddDependency failed,probably already exists\r\n"));
  381. }
  382. }
  383. }
  384. if (NULL != pWeb)
  385. pWeb->Release();
  386. if (pszGroupDesc)
  387. LocalFreeMem(pszGroupDesc);
  388. return hr;
  389. }
  390. /*++
  391. Routine Name:
  392. AddScriptAtPrinterVDir
  393. Description:
  394. Add the .printer and .asp script mapping at printers virtual directory
  395. Arguments:
  396. pIMetaBase - Pointer to the IIS Admin base
  397. Returns:
  398. An HRESULT
  399. --*/
  400. HRESULT
  401. AddScriptAtPrinterVDir(
  402. IMSAdminBase *pIMetaBase
  403. )
  404. {
  405. static WCHAR szScritMapFmt[] = L"%ws%c.printer,%ws\\msw3prt.dll,1,GET,POST%c";
  406. static WCHAR szPrinterVDir[] = L"w3svc/1/root/printers";
  407. METADATA_HANDLE hMeta = NULL; // handle to metabase
  408. PWCHAR pszFullFormat = NULL;
  409. DWORD dwMDRequiredDataLen;
  410. METADATA_RECORD mr;
  411. HRESULT hr = S_OK;
  412. DWORD nLen;
  413. WCHAR szSystemDir[MAX_PATH];
  414. PWCHAR pszAspMapping = NULL;
  415. DWORD dwMappingLen = 0;
  416. PWCHAR pszScriptMap = NULL;
  417. DBGMSG(DBG_INFO, ("Adding the ScriptMap\r\n"));
  418. //
  419. // Read any script map set at the top, on LM\w3svc where all other default ones are (e.g. .asp, etc.)
  420. //
  421. hr = pIMetaBase->OpenKey( METADATA_MASTER_ROOT_HANDLE,
  422. L"/LM",
  423. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
  424. MY_META_TIMEOUT,
  425. &hMeta);
  426. if ( SUCCEEDED(hr) )
  427. {
  428. mr.dwMDIdentifier = MD_SCRIPT_MAPS;
  429. mr.dwMDAttributes = 0;
  430. mr.dwMDUserType = IIS_MD_UT_FILE;
  431. mr.dwMDDataType = MULTISZ_METADATA;
  432. mr.dwMDDataLen = 0;
  433. mr.pbMDData = NULL;
  434. hr = pIMetaBase->GetData( hMeta, cszW3Svc, &mr, &dwMDRequiredDataLen );
  435. hr = hr == HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER) ? S_OK : E_FAIL;
  436. }
  437. if ( SUCCEEDED(hr) )
  438. {
  439. //
  440. // allocate for existing stuff plus our new script map.
  441. //
  442. pszFullFormat = new WCHAR[dwMDRequiredDataLen];
  443. hr = pszFullFormat? S_OK : E_OUTOFMEMORY;
  444. }
  445. if ( SUCCEEDED(hr) )
  446. {
  447. mr.dwMDIdentifier = MD_SCRIPT_MAPS;
  448. mr.dwMDAttributes = 0;
  449. mr.dwMDUserType = IIS_MD_UT_FILE;
  450. mr.dwMDDataType = MULTISZ_METADATA;
  451. mr.dwMDDataLen = dwMDRequiredDataLen * sizeof (WCHAR);
  452. mr.pbMDData = reinterpret_cast<unsigned char *>(pszFullFormat);
  453. hr = pIMetaBase->GetData( hMeta, cszW3Svc, &mr, &dwMDRequiredDataLen );
  454. }
  455. if ( SUCCEEDED(hr) )
  456. {
  457. pszAspMapping = IsStrInMultiSZ( pszFullFormat, L".asp" );
  458. hr = pszAspMapping? S_OK: E_FAIL;
  459. }
  460. if ( SUCCEEDED(hr) )
  461. {
  462. nLen = COUNTOF (szScritMapFmt) + MAX_PATH + lstrlen (pszAspMapping);
  463. pszScriptMap = new WCHAR[nLen];
  464. hr = pszScriptMap ? S_OK : E_OUTOFMEMORY;
  465. }
  466. if ( SUCCEEDED(hr) )
  467. {
  468. //
  469. // Return value is the length in chars w/o null char.
  470. //
  471. hr = GetSystemDirectory(szSystemDir, COUNTOF (szSystemDir)) > 0 ? S_OK : E_FAIL;
  472. }
  473. if ( SUCCEEDED(hr) )
  474. {
  475. PWSTR pszNewPos = NULL;
  476. hr = StringCchPrintfEx(pszScriptMap, nLen, &pszNewPos, NULL, 0, szScritMapFmt, pszAspMapping, L'\0', szSystemDir, L'\0');
  477. //
  478. // The actual number of characters in the string will be the number of
  479. // characters in the original string minus the remaining characters.
  480. //
  481. dwMappingLen = (DWORD)(pszNewPos - pszScriptMap);
  482. }
  483. if ( SUCCEEDED(hr) )
  484. {
  485. //
  486. // Write the new SCRIPT value
  487. //
  488. mr.dwMDIdentifier = MD_SCRIPT_MAPS;
  489. mr.dwMDAttributes = METADATA_INHERIT;
  490. mr.dwMDUserType = IIS_MD_UT_FILE;
  491. mr.dwMDDataType = MULTISZ_METADATA;
  492. mr.dwMDDataLen = sizeof (WCHAR) * (dwMappingLen + 1) ;
  493. mr.pbMDData = reinterpret_cast<unsigned char *>(pszScriptMap);
  494. hr = pIMetaBase->SetData(hMeta, szPrinterVDir, &mr );
  495. }
  496. if ( hMeta )
  497. {
  498. pIMetaBase->CloseKey( hMeta );
  499. hMeta = NULL;
  500. }
  501. delete [] pszScriptMap;
  502. delete [] pszFullFormat;
  503. return hr;
  504. }
  505. /*++
  506. Routine Name:
  507. AddMimeType
  508. Description:
  509. Add the .webpnp MimeType to the standard MimeType mappings
  510. Arguments:
  511. pIMetaBase - Pointer to the IIS Admin base
  512. Returns:
  513. An HRESULT
  514. --*/
  515. HRESULT
  516. AddMimeType(
  517. IMSAdminBase *pIMetaBase
  518. )
  519. {
  520. METADATA_HANDLE hMeta = NULL; // handle to metabase
  521. DWORD dwMDRequiredDataLen,
  522. dwCurrentMapBytes,
  523. dwWebPnPMapLen;
  524. METADATA_RECORD mr;
  525. HRESULT hr = S_OK;
  526. DWORD nLen;
  527. PWCHAR pszCurrentMimeMap = NULL;
  528. PWCHAR pszNewMimeMap = NULL;
  529. PWCHAR pszWebPnPMap = NULL;
  530. DWORD dwMappingLen = 0;
  531. DBGMSG(DBG_INFO, ("Adding the MimeType\r\n"));
  532. //
  533. // Read the current MimeType mapping, on LM\MimeMap
  534. //
  535. hr = pIMetaBase->OpenKey( METADATA_MASTER_ROOT_HANDLE,
  536. L"/LM",
  537. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
  538. MY_META_TIMEOUT,
  539. &hMeta);
  540. if ( SUCCEEDED(hr) )
  541. {
  542. mr.dwMDIdentifier = MD_MIME_MAP;
  543. mr.dwMDAttributes = 0;
  544. mr.dwMDUserType = IIS_MD_UT_FILE;
  545. mr.dwMDDataType = MULTISZ_METADATA;
  546. mr.dwMDDataLen = 0;
  547. mr.pbMDData = NULL;
  548. hr = pIMetaBase->GetData( hMeta, cszMimeMap, &mr, &dwCurrentMapBytes );
  549. hr = hr == HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER) ? S_OK : E_FAIL;
  550. }
  551. if ( SUCCEEDED(hr) )
  552. {
  553. //
  554. // allocate for existing stuff plus our new script map.
  555. //
  556. pszCurrentMimeMap = (PWCHAR) new BYTE[dwCurrentMapBytes];
  557. hr = pszCurrentMimeMap? S_OK : E_OUTOFMEMORY;
  558. }
  559. if ( SUCCEEDED(hr) )
  560. {
  561. mr.dwMDIdentifier = MD_MIME_MAP;
  562. mr.dwMDAttributes = 0;
  563. mr.dwMDUserType = IIS_MD_UT_FILE;
  564. mr.dwMDDataType = MULTISZ_METADATA;
  565. mr.dwMDDataLen = dwCurrentMapBytes;
  566. mr.pbMDData = reinterpret_cast<unsigned char *>(pszCurrentMimeMap);
  567. hr = pIMetaBase->GetData( hMeta, cszMimeMap, &mr, &dwMDRequiredDataLen );
  568. }
  569. if ( SUCCEEDED(hr) )
  570. {
  571. pszWebPnPMap = IsStrInMultiSZ( pszCurrentMimeMap, L".webpnp" );
  572. //
  573. // If the map doesn't currently exist
  574. //
  575. if (!pszWebPnPMap)
  576. {
  577. dwWebPnPMapLen = COUNTOF (cszWebPnPMap);
  578. nLen = (dwWebPnPMapLen * sizeof(WCHAR)) + dwCurrentMapBytes;
  579. pszNewMimeMap = (PWCHAR) new BYTE[nLen];
  580. hr = pszNewMimeMap ? S_OK : E_OUTOFMEMORY;
  581. if ( SUCCEEDED(hr) )
  582. {
  583. CopyMemory( pszNewMimeMap, // Remove our script map by copying the remainder of the multi_sz on top of the string containing the map.
  584. pszCurrentMimeMap,
  585. dwCurrentMapBytes);
  586. pszWebPnPMap = pszNewMimeMap + (dwCurrentMapBytes/sizeof(WCHAR));
  587. pszWebPnPMap--; // Back up onto the Double NULL
  588. hr = StringCchCopy(pszWebPnPMap, dwWebPnPMapLen, cszWebPnPMap);
  589. }
  590. if ( SUCCEEDED(hr) )
  591. {
  592. pszWebPnPMap+=dwWebPnPMapLen;
  593. *pszWebPnPMap = 0x00;
  594. //
  595. // Write the new MimeType Map value
  596. //
  597. mr.dwMDIdentifier = MD_MIME_MAP;
  598. mr.dwMDAttributes = METADATA_INHERIT;
  599. mr.dwMDUserType = IIS_MD_UT_FILE;
  600. mr.dwMDDataType = MULTISZ_METADATA;
  601. mr.dwMDDataLen = nLen;
  602. mr.pbMDData = reinterpret_cast<unsigned char *>(pszNewMimeMap);
  603. hr = pIMetaBase->SetData(hMeta, cszMimeMap, &mr );
  604. if (FAILED(hr))
  605. {
  606. DBGMSG(DBG_INFO, ("AddMimeType Failed. RC = %d\r\n", HRESULT_CODE(hr)));
  607. }
  608. }
  609. }
  610. }
  611. if ( hMeta )
  612. {
  613. pIMetaBase->CloseKey( hMeta );
  614. hMeta = NULL;
  615. }
  616. delete [] pszCurrentMimeMap;
  617. delete [] pszNewMimeMap;
  618. return hr;
  619. }
  620. DWORD
  621. RemoveWebPrinting(
  622. VOID
  623. )
  624. {
  625. IMSAdminBase* pIMetaBase = NULL;
  626. DWORD dwRet = NO_ERROR;
  627. HKEY hKey;
  628. DBGMSG(DBG_INFO, ("Removing Web Printing.\n"));
  629. //
  630. // Before we try to uninstall check to see is the WWW
  631. // service has already been uninstalled. If it is gone so are
  632. // all of our reg entries.
  633. //
  634. if( ERROR_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE, cszW3SvcReg, 0, KEY_READ, &hKey))
  635. {
  636. RegCloseKey( hKey );
  637. //
  638. // Init up the MetaBase
  639. //
  640. if ( SUCCEEDED(CoInitializeEx( NULL, COINIT_MULTITHREADED )))
  641. {
  642. if ( SUCCEEDED(::CoCreateInstance(CLSID_MSAdminBase,
  643. NULL,
  644. CLSCTX_ALL,
  645. IID_IMSAdminBase,
  646. (void **)&pIMetaBase)) )
  647. {
  648. HRESULT hr; // com error status
  649. METADATA_HANDLE hMeta = NULL; // handle to metabase
  650. //
  651. // First Remove the Virtual Directory
  652. //
  653. // Attempt to open the virtual dir set on Web server #1 (default server)
  654. hr = pIMetaBase->OpenKey( METADATA_MASTER_ROOT_HANDLE,
  655. cszW3SvcRootPath,
  656. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
  657. MY_META_TIMEOUT,
  658. &hMeta );
  659. // Create the key if it does not exist.
  660. if ( SUCCEEDED( hr ) )
  661. {
  662. pIMetaBase->DeleteKey( hMeta, cszPrinters ); // We don't check the retrun value since the key may already not exist and we could get an error for that reason.
  663. pIMetaBase->CloseKey( hMeta );
  664. hMeta = NULL;
  665. //
  666. // Next Remove the Web Extention Record & App Dependency
  667. //
  668. hr = RemoveWebExtension();
  669. if (SUCCEEDED(hr))
  670. {
  671. //
  672. // Next Remove the .printers ScriptMap
  673. //
  674. PWCHAR pszScripts = NULL,
  675. pszMimeMap = NULL;
  676. DWORD dwMDRequiredDataLen;
  677. METADATA_RECORD mr;
  678. // Read any script map set at the top, on LM\w3svc where all other default ones are (e.g. .asp, etc.)
  679. hr = pIMetaBase->OpenKey( METADATA_MASTER_ROOT_HANDLE,
  680. L"/LM",
  681. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
  682. MY_META_TIMEOUT,
  683. &hMeta);
  684. if ( SUCCEEDED( hr ) )
  685. {
  686. mr.dwMDIdentifier = MD_SCRIPT_MAPS;
  687. mr.dwMDAttributes = 0;
  688. mr.dwMDUserType = IIS_MD_UT_FILE;
  689. mr.dwMDDataType = MULTISZ_METADATA;
  690. mr.dwMDDataLen = 0;
  691. mr.pbMDData = NULL;
  692. hr = pIMetaBase->GetData( hMeta, cszW3Svc, &mr, &dwMDRequiredDataLen );
  693. if ( FAILED( hr ) )
  694. {
  695. if ( HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER )
  696. {
  697. // allocate for existing stuff
  698. pszScripts = new WCHAR[dwMDRequiredDataLen];
  699. if ( pszScripts )
  700. {
  701. mr.dwMDIdentifier = MD_SCRIPT_MAPS;
  702. mr.dwMDAttributes = 0;
  703. mr.dwMDUserType = IIS_MD_UT_FILE;
  704. mr.dwMDDataType = MULTISZ_METADATA;
  705. mr.dwMDDataLen = dwMDRequiredDataLen;
  706. mr.pbMDData = reinterpret_cast<unsigned char *>(pszScripts);
  707. hr = pIMetaBase->GetData( hMeta, cszW3Svc, &mr, &dwMDRequiredDataLen );
  708. if ( SUCCEEDED( hr ) )
  709. dwRet = WriteStrippedScriptValue( pIMetaBase, hMeta, pszScripts ); // Remove the .printer map from the multi_sz if there;
  710. delete pszScripts;
  711. }
  712. }
  713. }
  714. if ( SUCCEEDED( hr ) )
  715. {
  716. mr.dwMDIdentifier = MD_MIME_MAP;
  717. mr.dwMDAttributes = 0;
  718. mr.dwMDUserType = IIS_MD_UT_FILE;
  719. mr.dwMDDataType = MULTISZ_METADATA;
  720. mr.dwMDDataLen = 0;
  721. mr.pbMDData = NULL;
  722. hr = pIMetaBase->GetData( hMeta, cszMimeMap, &mr, &dwMDRequiredDataLen );
  723. if ( FAILED( hr ) )
  724. {
  725. if ( HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER )
  726. {
  727. // allocate for existing stuff
  728. pszMimeMap = (PWCHAR) new BYTE[dwMDRequiredDataLen];
  729. if ( pszMimeMap )
  730. {
  731. mr.dwMDIdentifier = MD_MIME_MAP;
  732. mr.dwMDAttributes = 0;
  733. mr.dwMDUserType = IIS_MD_UT_FILE;
  734. mr.dwMDDataType = MULTISZ_METADATA;
  735. mr.dwMDDataLen = dwMDRequiredDataLen;
  736. mr.pbMDData = reinterpret_cast<unsigned char *>(pszMimeMap);
  737. hr = pIMetaBase->GetData( hMeta, cszMimeMap, &mr, &dwMDRequiredDataLen );
  738. if ( SUCCEEDED( hr ) )
  739. dwRet = WriteStrippedMimeMapValue( pIMetaBase, hMeta, pszMimeMap ); // Remove the .printer map from the multi_sz if there;
  740. delete pszMimeMap;
  741. }
  742. }
  743. }
  744. }
  745. pIMetaBase->CloseKey( hMeta );
  746. }
  747. else
  748. dwRet = GetLastError();
  749. }
  750. else
  751. dwRet = GetLastError();
  752. }
  753. else
  754. dwRet = GetLastError();
  755. if (SUCCEEDED(hr))
  756. {
  757. hr = pIMetaBase->SaveData();
  758. dwRet = HRESULT_CODE(hr);
  759. }
  760. pIMetaBase->Release();
  761. }
  762. CoUninitialize();
  763. }
  764. }
  765. return dwRet;
  766. }
  767. HRESULT
  768. RemoveWebExtension(
  769. VOID
  770. )
  771. {
  772. WCHAR szExtPath[MAX_PATH];
  773. WCHAR szSystemPath[MAX_PATH];
  774. IISWebService* pWeb = NULL;
  775. DBGMSG(DBG_INFO, ("Removing the Web Extension\r\n"));
  776. HRESULT hr = ADsGetObject(cszWebSvcExtRestrictionListADSILocation, IID_IISWebService, (void**)&pWeb);
  777. if (SUCCEEDED(hr) && NULL != pWeb)
  778. {
  779. hr = GetSystemDirectory(szSystemPath, COUNTOF (szSystemPath)) > 0 ? S_OK : E_FAIL;
  780. if (SUCCEEDED(hr))
  781. {
  782. hr = StringCchPrintf(szExtPath, COUNTOF(szExtPath), cszExtPathFmt, szSystemPath);
  783. }
  784. if (SUCCEEDED(hr))
  785. {
  786. hr = pWeb->DeleteExtensionFileRecord(szExtPath);
  787. }
  788. if (FAILED(hr))
  789. {
  790. DBGMSG(DBG_INFO, ("DeleteExtension failed,probably already gone\r\n"));
  791. }
  792. }
  793. if (SUCCEEDED(hr) && NULL != pWeb)
  794. {
  795. LPTSTR pszGroupDesc = GetStringFromRcFile(IDS_INTERNET_PRINTING);
  796. hr = (pszGroupDesc ? S_OK : E_FAIL);
  797. if (SUCCEEDED(hr))
  798. {
  799. hr = pWeb->RemoveDependency((LPWSTR) pszGroupDesc,(LPWSTR) cszASPId);
  800. }
  801. if (FAILED(hr))
  802. {
  803. DBGMSG(DBG_INFO, ("RemoveDep failed,probably already gone\r\n"));
  804. }
  805. if (pszGroupDesc)
  806. LocalFreeMem(pszGroupDesc);
  807. }
  808. if (NULL != pWeb)
  809. pWeb->Release();
  810. return hr;
  811. }
  812. //
  813. //
  814. // Finds and removed our script map from the multi_sz, and writes it back to the metabase.
  815. //
  816. //
  817. DWORD
  818. WriteStrippedScriptValue(
  819. IMSAdminBase *pIMetaBase,
  820. METADATA_HANDLE hMeta, // Handle to /LM tree
  821. PWCHAR pszScripts // MULTI_SZ string already there
  822. )
  823. {
  824. LPWSTR pStrToKill, pNextStr;
  825. HRESULT hr;
  826. DBGMSG(DBG_INFO, ("Removing the ScriptMap\r\n"));
  827. // See if our script map is already there.
  828. if ( !(pStrToKill = IsStrInMultiSZ( pszScripts, L".printer" )) )
  829. return NO_ERROR;
  830. // Find the next string (could be the final NULL char)
  831. pNextStr = pStrToKill + (wcslen(pStrToKill) + 1);
  832. if ( !*pNextStr )
  833. *pStrToKill = 0; // Our scipt map was at the end of multi_sz. Write the 2nd NULL char and we are done.
  834. else
  835. CopyMemory( pStrToKill, // Remove our script map by copying the remainder of the multi_sz on top of the string containing the map.
  836. pNextStr,
  837. GetMultiSZLen(pNextStr) * sizeof(WCHAR));
  838. // Write the new SCRIPT value
  839. METADATA_RECORD mr;
  840. mr.dwMDIdentifier = MD_SCRIPT_MAPS;
  841. mr.dwMDAttributes = METADATA_INHERIT;
  842. mr.dwMDUserType = IIS_MD_UT_FILE;
  843. mr.dwMDDataType = MULTISZ_METADATA;
  844. mr.dwMDDataLen = GetMultiSZLen(pszScripts) * sizeof(WCHAR);
  845. mr.pbMDData = reinterpret_cast<unsigned char *>(pszScripts);
  846. hr = pIMetaBase->SetData( hMeta, cszW3Svc, &mr );
  847. return( HRESULT_CODE( hr ));
  848. }
  849. //
  850. //
  851. // Finds and removed our .webpnp MimeType from the multi_sz, and writes it back to the metabase.
  852. //
  853. //
  854. DWORD
  855. WriteStrippedMimeMapValue(
  856. IMSAdminBase *pIMetaBase,
  857. METADATA_HANDLE hMeta, // Handle to /LM tree
  858. PWCHAR pszMimeMap // MULTI_SZ string already there
  859. )
  860. {
  861. LPWSTR pStrToKill, pNextStr;
  862. HRESULT hr;
  863. DBGMSG(DBG_INFO, ("Removing the MimeType\r\n"));
  864. // See if our script map is already there.
  865. if ( !(pStrToKill = IsStrInMultiSZ( pszMimeMap, L".webpnp" )) )
  866. return NO_ERROR;
  867. // Find the next string (could be the final NULL char)
  868. pNextStr = pStrToKill + (wcslen(pStrToKill) + 1);
  869. if ( !*pNextStr )
  870. *pStrToKill = 0; // Our scipt map was at the end of multi_sz. Write the 2nd NULL char and we are done.
  871. else
  872. CopyMemory( pStrToKill, // Remove our script map by copying the remainder of the multi_sz on top of the string containing the map.
  873. pNextStr,
  874. GetMultiSZLen(pNextStr) * sizeof(WCHAR));
  875. // Write the new SCRIPT value
  876. METADATA_RECORD mr;
  877. mr.dwMDIdentifier = MD_MIME_MAP;
  878. mr.dwMDAttributes = METADATA_INHERIT;
  879. mr.dwMDUserType = IIS_MD_UT_FILE;
  880. mr.dwMDDataType = MULTISZ_METADATA;
  881. mr.dwMDDataLen = GetMultiSZLen(pszMimeMap) * sizeof(WCHAR);
  882. mr.pbMDData = reinterpret_cast<unsigned char *>(pszMimeMap);
  883. hr = pIMetaBase->SetData( hMeta, cszMimeMap, &mr );
  884. return( HRESULT_CODE( hr ));
  885. }
  886. //
  887. //
  888. // Finds the string pSearch in pSrc buffer and returns a ptr to the occurance of pSearch in pSrc.
  889. //
  890. //
  891. LPWSTR mystrstrni( LPWSTR pSrc, LPWSTR pSearch )
  892. {
  893. UINT uSearchSize = wcslen( pSearch );
  894. UINT uSrcSize = wcslen( pSrc );
  895. LPCTSTR pEnd;
  896. if ( uSrcSize < uSearchSize )
  897. return(NULL);
  898. pEnd = pSrc + uSrcSize - uSearchSize;
  899. for ( ; pSrc <= pEnd; ++pSrc )
  900. {
  901. if ( !_wcsnicmp( pSrc, pSearch, uSearchSize ) )
  902. return((LPWSTR)pSrc);
  903. }
  904. return(NULL);
  905. }
  906. //
  907. // Determines if the string pSearch can be found inside of a MULTI_SZ string. If it can, it retunrs a
  908. // pointer to the beginning of the string in multi-sz that contains pSearch.
  909. //
  910. LPWSTR IsStrInMultiSZ( LPWSTR pMultiSzSrc, LPWSTR pSearch )
  911. {
  912. LPWSTR pTmp = pMultiSzSrc;
  913. while ( TRUE )
  914. {
  915. if ( mystrstrni( pTmp, pSearch ) ) // See pSearch (i.e. ".printer" appears anywhere within this string. If it does, it must be ours.
  916. return pTmp;
  917. pTmp = pTmp + (wcslen(pTmp) + 1); // Point to the beginning of the next string in the MULTI_SZ
  918. if ( !*pTmp )
  919. return NULL; // reached the end of the MULTI_SZ string.
  920. }
  921. }
  922. /*++
  923. Routine Name
  924. GetMultiSZLen
  925. Routine Description:
  926. This returns the number of characters in a multisz string, including NULLs.
  927. Arguments:
  928. pMultiSzSrc - The multisz string to search.
  929. Return Value:
  930. The number of characters in the string.
  931. --*/
  932. DWORD
  933. GetMultiSZLen(
  934. IN LPWSTR pMultiSzSrc
  935. )
  936. {
  937. DWORD dwLen = 0;
  938. LPWSTR pTmp = pMultiSzSrc;
  939. while( TRUE ) {
  940. dwLen += wcslen(pTmp) + 1; // Incude the terminating NULL char
  941. pTmp = pMultiSzSrc + dwLen; // Point to the beginning of the next string in the MULTI_SZ
  942. if( !*pTmp )
  943. return ++dwLen; // Reached the end of the MULTI_SZ string. Add 1 to the count for the last NULL char.
  944. }
  945. }
  946. //
  947. // Routine: IppOcEntry
  948. //
  949. DWORD
  950. IppOcEntry(
  951. IN LPCVOID ComponentId,
  952. IN LPCVOID SubcomponentId,
  953. IN UINT Function,
  954. IN UINT Param1,
  955. IN OUT PVOID Param2
  956. )
  957. {
  958. BOOL bWrongCompId = TRUE;
  959. DWORD dwRet = NO_ERROR;
  960. static MYSETUPSTRUCT* pMySetupInfo = NULL;
  961. //
  962. // Check if the ComponentId is correct
  963. //
  964. if ( ComponentId )
  965. bWrongCompId = _tcsicmp(cszComponentId, (LPCTSTR) ComponentId);
  966. switch ( Function )
  967. {
  968. case OC_PREINITIALIZE:
  969. DBGMSG(DBG_INFO, ("In OC_PREINITIALIZE.\n"));
  970. //
  971. // We are just starting up
  972. //
  973. if ( bWrongCompId ||
  974. !(Param1 && OCFLAG_UNICODE) )
  975. dwRet = 0;
  976. else
  977. dwRet = OCFLAG_UNICODE;
  978. //
  979. // Cleanup Any leftover data
  980. //
  981. if ( pMySetupInfo )
  982. {
  983. LocalFree(pMySetupInfo);
  984. pMySetupInfo = NULL;
  985. }
  986. break;
  987. case OC_INIT_COMPONENT:
  988. DBGMSG(DBG_INFO, ("In OC_INIT_COMPONENT.\n"));
  989. {
  990. //
  991. // Setup our Internal info
  992. //
  993. PSETUP_INIT_COMPONENT pInputData = (PSETUP_INIT_COMPONENT) Param2;
  994. if ( bWrongCompId ||
  995. !pInputData ||
  996. (HIWORD(pInputData->OCManagerVersion) < OCVER_MAJOR) )
  997. {
  998. dwRet = ERROR_CALL_NOT_IMPLEMENTED;
  999. }
  1000. else
  1001. {
  1002. //
  1003. // We have a good version of the OCM
  1004. //
  1005. // Set our desired version
  1006. pInputData->ComponentVersion = OCMANAGER_VERSION;
  1007. //
  1008. // Save away the usefal data
  1009. //
  1010. pMySetupInfo = (MYSETUPSTRUCT*) LocalAlloc(LPTR, sizeof(MYSETUPSTRUCT));
  1011. if ( pMySetupInfo )
  1012. {
  1013. // Copy the SetupData
  1014. CopyMemory(&pMySetupInfo->OCData, &pInputData->SetupData, sizeof(SETUP_DATA));
  1015. // Copy Helper Routines Function Pointers
  1016. CopyMemory(&pMySetupInfo->OCHelpers, &pInputData->HelperRoutines, sizeof(OCMANAGER_ROUTINES));
  1017. // Set the FirstPass flag
  1018. pMySetupInfo->bFirstCall = TRUE;
  1019. dwRet = NO_ERROR;
  1020. }
  1021. else
  1022. dwRet = GetLastError();
  1023. }
  1024. }
  1025. break;
  1026. case OC_SET_LANGUAGE:
  1027. //
  1028. // Don't Fail since we doan't actually need language support
  1029. //
  1030. dwRet = TRUE;
  1031. break;
  1032. case OC_QUERY_CHANGE_SEL_STATE:
  1033. //
  1034. // If we are getting asked to be turned on because our parent was selected -
  1035. //
  1036. if (Param1 &&
  1037. (((UINT) (ULONG_PTR)Param2) & OCQ_DEPENDENT_SELECTION) &&
  1038. !(((UINT) (ULONG_PTR)Param2) & OCQ_ACTUAL_SELECTION ))
  1039. {
  1040. // Don't do it...
  1041. dwRet = FALSE;
  1042. }
  1043. else
  1044. {
  1045. // Otherwise it is OK.
  1046. dwRet = TRUE;
  1047. }
  1048. break;
  1049. case OC_QUERY_STEP_COUNT:
  1050. //
  1051. // We only have one step
  1052. // Create/Delete the VDIR & ScriptMap
  1053. //
  1054. dwRet = 1;
  1055. break;
  1056. case OC_COMPLETE_INSTALLATION:
  1057. DBGMSG(DBG_INFO, ("In OC_COMPLETE_INSTALLATION.\n"));
  1058. //
  1059. // Check the state of the Checkbox and either create or delete the VDIR.
  1060. //
  1061. if ( !bWrongCompId &&
  1062. pMySetupInfo && pMySetupInfo->OCHelpers.QuerySelectionState )
  1063. {
  1064. //
  1065. // If this is the first call then skip until more things are installed.
  1066. //
  1067. if (pMySetupInfo->bFirstCall)
  1068. {
  1069. pMySetupInfo->bFirstCall = FALSE;
  1070. }
  1071. else
  1072. {
  1073. BOOL bDoInstall;
  1074. //
  1075. // Get the current selection state
  1076. //
  1077. bDoInstall = pMySetupInfo->OCHelpers.QuerySelectionState( pMySetupInfo->OCHelpers.OcManagerContext,
  1078. cszComponentId, OCSELSTATETYPE_CURRENT);
  1079. if ( (NO_ERROR == GetLastError()) &&
  1080. (bDoInstall != pMySetupInfo->bInitState) )
  1081. {
  1082. //
  1083. // We got a valid state
  1084. //
  1085. LPTSTR pszProcessInfo = NULL;
  1086. STARTUPINFO StartUpInfo;
  1087. PROCESS_INFORMATION ProcInfo;
  1088. //
  1089. // Call Create Process
  1090. //
  1091. if ( bDoInstall )
  1092. pszProcessInfo = AllocStr(cszInstallInetPrint);
  1093. else
  1094. pszProcessInfo = AllocStr(cszRemoveInetPrint);
  1095. if (pszProcessInfo)
  1096. {
  1097. //
  1098. // Init the Startup Info
  1099. //
  1100. memset(&StartUpInfo, 0, sizeof(STARTUPINFO));
  1101. StartUpInfo.cb = sizeof(STARTUPINFO);
  1102. if (CreateProcess( NULL, pszProcessInfo, NULL, NULL, FALSE,
  1103. (CREATE_NO_WINDOW|NORMAL_PRIORITY_CLASS), NULL, NULL, &StartUpInfo, &ProcInfo))
  1104. {
  1105. //
  1106. // Wait on the process handle
  1107. //
  1108. WaitForSingleObject( ProcInfo.hProcess, INFINITE);
  1109. //
  1110. // Get the Process Exit Code
  1111. //
  1112. if (!GetExitCodeProcess( ProcInfo.hProcess, &dwRet ))
  1113. dwRet = GetLastError();
  1114. //
  1115. // CLose the Preocess & Thread Handles
  1116. //
  1117. CloseHandle(ProcInfo.hProcess);
  1118. CloseHandle(ProcInfo.hThread);
  1119. }
  1120. else
  1121. dwRet = GetLastError();
  1122. LocalFree(pszProcessInfo);
  1123. }
  1124. else
  1125. dwRet = GetLastError();
  1126. if (NO_ERROR == dwRet)
  1127. {
  1128. HANDLE hServer;
  1129. DWORD dwInstallWebPrinting = bDoInstall,
  1130. dwLastError,
  1131. dwType = REG_DWORD;
  1132. PRINTER_DEFAULTS Defaults = {NULL, NULL, SERVER_ACCESS_ADMINISTER};
  1133. if ( !OpenPrinter(NULL, &hServer, &Defaults) )
  1134. return FALSE;
  1135. dwLastError = SetPrinterData(hServer,
  1136. SPLREG_WEBSHAREMGMT,
  1137. dwType,
  1138. (LPBYTE)&dwInstallWebPrinting,
  1139. sizeof(dwInstallWebPrinting));
  1140. ClosePrinter(hServer);
  1141. }
  1142. }
  1143. }
  1144. }
  1145. DBGMSG(DBG_INFO, ("Exitting OC_COMPLETE_INSTALLATION. RC = %d\n", dwRet));
  1146. break;
  1147. case OC_CLEANUP:
  1148. DBGMSG(DBG_INFO, ("In OC_CLEANUP.\n"));
  1149. //
  1150. // The install is done or cancelled so cleanup the allocated memory
  1151. //
  1152. if ( pMySetupInfo )
  1153. {
  1154. LocalFree(pMySetupInfo);
  1155. pMySetupInfo = NULL;
  1156. }
  1157. break;
  1158. case OC_QUERY_STATE:
  1159. DBGMSG(DBG_INFO, ("In OC_QUERY_STATE.\n"));
  1160. //
  1161. // Figure out if the VDIR exists to set the initial state of the checkbox.
  1162. //
  1163. if ( !bWrongCompId &&
  1164. (Param1 == OCSELSTATETYPE_ORIGINAL) )
  1165. {
  1166. //
  1167. // If we are upgrading we need to run the install code as if we aren't currently installed
  1168. // otherwise save away the initial state
  1169. //
  1170. pMySetupInfo->bInitState = IsVDIRInstalled();
  1171. if (pMySetupInfo->bInitState)
  1172. dwRet = SubcompOn;
  1173. else
  1174. dwRet = SubcompOff;
  1175. if (pMySetupInfo->OCData.OperationFlags & SETUPOP_NTUPGRADE)
  1176. {
  1177. pMySetupInfo->bInitState = FALSE;
  1178. DBGMSG(DBG_INFO, ("Performing NT Upgrade.\n"));
  1179. }
  1180. DBGMSG(DBG_INFO, ("Current Componenet state = %d.\n", dwRet));
  1181. }
  1182. break;
  1183. default:
  1184. break;
  1185. }
  1186. return dwRet;
  1187. }
  1188. void CALLBACK SetupInetPrint(
  1189. IN HWND hwnd, // handle to owner window
  1190. IN HINSTANCE hinst, // instance handle for the DLL
  1191. IN LPSTR lpCmdLine, // string the DLL will parse
  1192. IN int nCmdShow // show state
  1193. )
  1194. {
  1195. DWORD dwRet;
  1196. //
  1197. // Check Cmdline for either Install or Remove parameters
  1198. if ( !_strnicmp( lpCmdLine, cszInstall, COUNTOF(cszInstall)) )
  1199. dwRet = InstallWebPrinting();
  1200. else if ( !_strnicmp( lpCmdLine, cszRemove, COUNTOF(cszRemove)) )
  1201. dwRet = RemoveWebPrinting();
  1202. else
  1203. dwRet = ERROR_INVALID_PARAMETER;
  1204. ExitProcess(dwRet);
  1205. }