Archive for July 2010

StarCraft II available for predownload

I am downloading StarCraft II right now.

Supposedly you can download it, then purchase your activation key online and install and activate tomorrow.

It is available for pre-download here.

http://www.starcraft2.com/

FreeBSD 8.1 Released today!

So I was browsing the FreeBSD Ftp yesterday and saw that FreeBSD 8.1-Release ISOs were available, and I almost jumped the gun and announced this yesterday.

http://www.freebsd.org/news/newsflash.html#event20100723:01

Duct Tape recommended to fix the iPhone4!

Yes, Duct Tape gets to add one more use to it already long bag of tricks.

Ok, this is seriously hilarious. Consumer Reports is very reputable. They don’t recommend the iPhone4 but recommend that if you have one, you fix it with Duct Tape.

Can there be anything funnier?

http://finance.yahoo.com/tech-ticker/article/519336/Consumer-Reports-Findings-Conflict-With-Apples-Statement-On-iPhone-4

How do you know all software programmers are crazy?

Question: How do you know all software programmers are crazy?

Answer: All their code has to be committed.

A Laffy Taffy style joke by Mark Minson

A simple example of starting and stopping a service in windows using C++

Hey all,

Here is a simple example of starting and stopping a service in C++. Just pass the service name as a parameter and the service will switch states. If stopped, it will start. If started, it will stop.

// StartStopService.cpp : Defines the entry point for the console application.
//

#include “stdafx.h”
#include
#include

int _tmain(int argc, _TCHAR* argv[])
{
SC_HANDLE serviceDbHandle = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
SC_HANDLE serviceHandle = OpenService(serviceDbHandle, argv[1], SC_MANAGER_ALL_ACCESS);

SERVICE_STATUS_PROCESS status;
DWORD bytesNeeded;
QueryServiceStatusEx(serviceHandle, SC_STATUS_PROCESS_INFO,(LPBYTE) &status,sizeof(SERVICE_STATUS_PROCESS), &bytesNeeded);

if (status.dwCurrentState == SERVICE_RUNNING)
{// Stop it
BOOL b = ControlService(serviceHandle, SERVICE_CONTROL_STOP, (LPSERVICE_STATUS) &status);
if (b)
{
std::cout << "Service stopped." << std::endl; } else { std::cout << "Service failed to stop." << std::endl; } } else {// Start it BOOL b = StartService(serviceHandle, NULL, NULL); if (b) { std::cout << "Service started." << std::endl; } else { std::cout << "Service failed to start." << std::endl; } } CloseServiceHandle(serviceHandle); CloseServiceHandle(serviceDbHandle); return 0; } [/sourcecode]

A simple example of creating or deleting a windows share using C++

Hey all,

Here is a simple example of creating or deleting a windows share in C++.

// CreateShare.cpp : Defines the entry point for the console application.
//

#include “stdafx.h”
#include
#include
#include “lm.h”

int _tmain(int argc, _TCHAR* argv[])
{
// Create share
if (0 == _tcscmp(argv[1], _T(“create”)))
{
SHARE_INFO_2 si =
{
L”ShareName”,
STYPE_DISKTREE,
L”Any nice comment or remark”,
ACCESS_READ,
DWORD(-1),
0,
L”C:\\Users\\jbarneck\\Desktop\\Share”,
L””
};

DWORD parameterError = 0;
DWORD status = NetShareAdd(NULL, 2, (BYTE *) &si, &parameterError);
if (status != ERROR_SUCCESS)
{
std::cout << "Error: " << status << std::endl; if (status == ERROR_ACCESS_DENIED) // 5L in WinError.h { std::cout << "Access denied." << std::endl; } if (status == NERR_ServerNotStarted) // 2114 in LMErr.h { std::cout << "The Server service is stopped." << std::endl; } if (status == NERR_DuplicateShare) // 2118 in LMErr.h { std::cout << "The share already exists." << std::endl; } } // End program return 0; } // Delete share if (0 == _tcscmp(argv[1], _T("delete"))) { DWORD status = NetShareDel(NULL, L"ShareName", 0); if (status != ERROR_SUCCESS) { std::cout << "Could not delete share: " << status << std::endl; } // End program return 0; } } [/sourcecode] References: NetShareAdd - http://msdn.microsoft.com/en-us/library/bb525384%28VS.85%29.aspx NetShareDel - http://msdn.microsoft.com/en-us/library/bb525386%28v=VS.85%29.aspx

How to determine if an MSI patch (.msp file) has been applied using C++?

Ok, so I need to determine if a patch has been applied to an MSI. Lets start with Enumerating the installed products and enumerating all the patches applied for each installed product.

I guess the title should be “How to enumerate installed MSI products and their applied MSP patches.”

I have to do it in C++, which is a drag because it looked like three lines of code in C#, but hey, maybe it isn’t so hard with C++ using .NET as well.

I researched on MSDN, of course.  It looks like I need to use this function: MsiGetPatchInfoEx.  However, I need to know the MSI GUID in order to use that function, so I might as well learn to use the MsiEnumProducts, MsiGetProductInfo, MsiEnumPatches to match the Product to an MSI Guid and that to a patch.

Creating the Project

  1. I created a new Project in Visual Studio to test this out. The project type I used was under C++ and is called Win32 Console application.
  2. I didn’t make any changes to the default code provided: targetver.h, stafx.h, stafx.cpp.
  3. Make sure you have the Platform SDK installed for the next step.
  4. I went to the project properties and went to Linker | Inpuut and added to Additional Dependencies the following line:
    "$(WindowsSdkDir)Lib\msi.lib"
    
  5. I wrote my code.

Learning the Code
So here is what the code I wrote in this little learning project will do:

  1. Create a list or vector to store each MSIProduct.
  2. Loop through each installed MSIs using the MsiEnumProducts function and for each installed MSI:
  3. Get MSI information using MSIProductInfo.
  4. Create an MSIProduct object using the information from MSIProductInfo and add the MSIProduct to the list or vector.
  5. Write to standard output the MSI count (as Id), the MSI name, and the MSI Guid.
  6. Create a list or vector to store each MSIPatch.
  7. Check if any patches or MSPs are applied to the MSI and for each patch:
  8. Get MSP information using MSIPatchInfoEx.
  9. Create an MSIPatch object using the information from MSIPatchInfoEx and add the MSIPatch to this list or vector.
  10. Write to standard output the MSP Guid.

Here is my code:

Run.cpp
This file does all the work and has the tmain function. It creates a list or vector of MSIProduct objects and then uses MsiEnumProducts and MsiGetProductInfo to create and add each MSIProduct to the vector.  It also loops through each of the MSIProduct‘s and find any installed patches.  It adds each patch found to the MSIProduct‘s _Patches vector.

// Run.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "windows.h"
#include "Msi.h"
#include "MSIProduct.h" // Includes MSIBase.h and MSIPatch.h as well
#include <iostream>
#include <vector>

using namespace std;

#define MYSIZE 512

int _tmain(int argc, _TCHAR* argv[])
{
	// Step 1. Create a list or vector to store each MSIProduct.
	vector<MSIProduct> *products = new vector<MSIProduct>();

	// Step 2. Loop through each installed MSIs using the MsiEnumProducts
	//            function and for each installed MSI:
	int i = 0;
	bool foundMoreApps = true;
	while (foundMoreApps)
	{
		DWORD size = MYSIZE;
		LPTSTR tmpGuid = new TCHAR[MYSIZE];
		LPTSTR tmpName = new TCHAR[MYSIZE];

		UINT ret1 = MsiEnumProducts(i, tmpGuid);
		if (ret1 > 0)
		{
			foundMoreApps = false;
			continue;
		}

		// Step 3. Get MSI information using MSIProductInfo.
		UINT ret2 = MsiGetProductInfo(tmpGuid, INSTALLPROPERTY_PRODUCTNAME, tmpName, &size);
		if (ret2 > 0)
		{
			// Todo: Handle failure
		}

		// Step 4. Create an MSIProduct object using the information from MSIProductInfo
		//            and add the MSIProduct to the list or vector.
		products->push_back(MSIProduct());
		products->at(i).SetName(tmpName);
		products->at(i).SetGuid(tmpGuid);

		// Step 5. Write to standard output the MSI count (as Id), the MSI name, and the MSI Guid.
		cout << endl;
		cout << "Id: " << i << endl;
		wcout << "Product: " << tmpName << endl;
		wcout << "Guid: " << tmpGuid << endl;
		cout << "Patches: ";

		// Step 6. Create a list or vector to store each MSIPatch.
		vector<MSIPatch> *patches = new vector<MSIPatch>();
		products->at(i).SetPatches(patches);

		// Step 7. Check if any patches or MSPs are applied to the MSI and for each patch:
		int j = 0;
		bool foundMorePatches = true;
		while (foundMorePatches)
		{
			DWORD size = MYSIZE;
			LPTSTR tmpPatchGuid = new TCHAR[MYSIZE];
			LPTSTR tmpPatchState = new TCHAR[MYSIZE];
			LPTSTR tmpPatchTransforms = new TCHAR[MYSIZE];

			UINT retPatch1 = MsiEnumPatches(tmpGuid, j, tmpPatchGuid, tmpPatchTransforms, &size);
			if (retPatch1 > 0)
			{
				cout << "(" << retPatch1 << ") :" << endl;
				foundMorePatches = false;
				continue;
			}

			// These values correspond to the constants the dwFilter parameter
			// of MsiEnumPatchesEx uses.

			// Step 8. Get MSP information using MSIPatchInfoEx.
			UINT retPatch2 = MsiGetPatchInfoEx(tmpPatchGuid, tmpGuid, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_PATCHSTATE, tmpPatchState, &size);
			// Returns "1" if this patch is currently applied to the product.
			// Returns "2" if this patch is superseded by another patch.
			// Returns "4" if this patch is obsolete.
			if (retPatch2 > 0)
			{
				// Todo: Handle failure
			}

			// Step 9. Create an MSIPatch object using the information from MSIPatchInfoEx
			//            and add the MSIPatch to this list or vector.
			patches->push_back(MSIPatch());
			patches->at(j).SetPatchState(tmpPatchState);
			patches->at(j).SetGuid(tmpPatchGuid);
			patches->at(j).SetTransforms(tmpPatchTransforms);

			// Step 9. Write to standard output the MSP Guid.
			wcout << "\t" << "Patch Guid: " << tmpPatchGuid << endl;

			j++;
		}

		i++;
	}
}
&#91;/sourcecode&#93;

I did create some simple supporting classes for this:

<strong>MSIBase.h</strong>


#pragma once
#include "windows.h"

class MSIBase
{
  public:

	// Constructor
	MSIBase(void);

	// Destructor
	virtual ~MSIBase(void);

	// Accessor functions
	LPTSTR GetName();
	void SetName(LPTSTR inName);

	LPTSTR GetGuid();
	void SetGuid(LPTSTR inGuid);

  protected:
	LPTSTR _Guid;
	LPTSTR _Name;
};

MSIBase.cpp

#include "StdAfx.h"
#include "MSIBase.h"

MSIBase::MSIBase(void)
{
}

MSIBase::~MSIBase(void)
{
}

// Accessor functions
LPTSTR  MSIBase::GetName()
{
	return _Name;
}

void MSIBase::SetName(LPTSTR inName)
{
	_Name = inName;
}

LPTSTR  MSIBase::GetGuid()
{
	return _Guid;
}

void MSIBase::SetGuid(LPTSTR inGuid)
{
	_Guid = inGuid;
}

MSIProduct.h

#include "MSIBase.h"
#include "MSIPatch.h"
#include <vector>

#pragma once
class MSIProduct : public MSIBase
{
public:
	MSIProduct(void);
	~MSIProduct(void);

	std::vector<MSIPatch> GetPatches();
	void SetPatches(std::vector<MSIPatch> * inPatches);
	void AddPatch(MSIPatch inPatch);

protected:
	std::vector<MSIPatch> * _Patches;
};

MSIProduct.cpp

#include "StdAfx.h"
#include "MSIProduct.h"

MSIProduct::MSIProduct(void)
{
}

MSIProduct::~MSIProduct(void)
{
	delete _Patches;
}

std::vector<MSIPatch> MSIProduct::GetPatches()
{
	return * _Patches;
}

void MSIProduct::SetPatches(std::vector<MSIPatch> * inPatches)
{
	_Patches = inPatches;
}

void MSIProduct::AddPatch(MSIPatch inPatch)
{
	_Patches->push_back(inPatch);
}

MSIPatch.h

#pragma once
#include "MSIBase.h"

class MSIPatch : public MSIBase
{
public:
	MSIPatch(void);
	~MSIPatch(void);

	LPTSTR GetTransforms();
	void SetTransforms(LPTSTR inTransforms);
	int GetPatchState();
	void SetPatchState(int inPatchState);
	void SetPatchState(LPTSTR inPatchState);

protected:
	LPTSTR _Transforms;
	int _PatchState;
};

MSIPatch.cpp

#include "StdAfx.h"
#include "MSIPatch.h"

MSIPatch::MSIPatch(void)
{
}

MSIPatch::~MSIPatch(void)
{
}

LPTSTR  MSIPatch::GetTransforms()
{
	return _Transforms;
}

void MSIPatch::SetTransforms(LPTSTR inTransforms)
{
	_Transforms = inTransforms;
}

int  MSIPatch::GetPatchState()
{
	return _PatchState;
}

void MSIPatch::SetPatchState(int inPatchState)
{
	_PatchState = inPatchState;

}

void MSIPatch::SetPatchState(LPTSTR inPatchState)
{
	_PatchState = _wtoi(inPatchState);
}

Sorry, I am not explaining in more detail, my time is limited.

Note: I found one problem where an application has a ™ in the name. (Skype™ 4.2) and the output doesn’t work well after that.


Copyright ® Rhyous.com – Linking to this article is allowed without permission and as many as ten lines of this article can be used along with this link. Any other use of this article is allowed only by permission of Rhyous.com.