CVS and Windows development tools

Microsoft defines two interfaces for source code control products: the Microsoft Common Source Code Control (SCC) API and an OLE Automation interface. CVS needs an implement one or both of these interfaces to integrate with Windows development tools.

Many Windows development environments can (and do) interface to a version control system through the SCC API interface. The OLE Automation interface, though perhaps better designed, is not in even remotely as wide use.

Since I tend to do most of my work on Windows, I have an interest in integrating CVS with Windows development tools. Not so much for myself as I'm pretty comfortable with the command line (spent a lot of time with Unix :-), however some of my compatriots would like something friendlier.

So after a brief and nearly fruitless attempt to reverse engineer the SCC API I signed the Microsoft NDA and received the official documentation. This introduced a constraint with which I was not comfortable:

Sources containing materials covered by the Microsoft NDA are not freely distributable.
That's the bad news. The good news is that you probably don't care.

To make it possible to freely distribute as much as possible of this project, I have split the implementation into two parts.

  1. The CVSSCC DLL that is directly loaded by Windows IDEs that use the SCC API.
  2. Any CVS GUI (WinCVS as one potential example) that implements the CVS Coworker COM interface.
CVSSCC.DLL is written and pretty stable. If you download the CVSSCC.DLL that I have built, you do notneed to sign the Microsoft NDA. Using CVSSCC.DLL anyone can write an GUI interface to CVS that (through CVSSCC) is tightly integrated into any existing Windows IDE that uses the SCC API.

What remains to be done is to write a nice GUI for CVS.

CVSSCC uses COM to interface with the GUI. This is configurable so that anyonecan write a CVS GUI and tie into the SCC API through CVSSCC. I have written example "coworkers" to show how the COM interface is implemented. I have even added the "coworker" interface into WinCVS - but only the interface, it is not connected to actual CVS functions within WinCVS.

That pretty much sums up where I'm at with this project...

Microsoft's SCC API

Microsoft Developer Studio 4.0 defines an interface for integrating source-code control. Once a source-code control system is installed that conforms to the Microsoft Common Source Code Control Interface, the user interface alters (added menus, appearance of files in project window) to reflect the operations offered by the source code control implementation, and to reflect the status of the files (if under source code control).

Unfortunately the documentation for the API is not publicly available. You can get the documentationof the interface from Microsoft, by signing a non-disclosure. The SCC API appears to be oriented more toward an RCS/SCCS/SourceSafe style interface - individual file check-in, check-out locked/unlocked, etc. Mapping CVS to this interface in any sort of intelligent manner should be interesting.

Products believed able to usethe SCC API:

Products that are known or believed to have implementedthe SCC API: As you might guess, I would like to add CVS to this list :-).

Microsoft's OLE Automation interface

Microsoft Visual SourceSafe 5.0 provides an implementation of the OLE Automation interface that is officially meant to replace the SCC API. Unfortunately this is entirely different from the SCC API (at least on the surface).

Microsoft Visual Studio 6.0 apparently still uses the SCC API rather than using the "official" OLE automation interface. In fact Visual SourceSafe 5.0 implements both the OLE Automation interface and the SCC API. Lucky for us :-).

Registry entries required by the SCC API

To discover the source code provider you start first with the registry entry:
[HKEY_LOCAL_MACHINE\SOFTWARE\SourceCodeControlProvider]
"ProviderRegKey"="Software\\Microsoft\\SourceSafe"
The value under ProviderRegKeyis the subkey that tells us what DLL to load:
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SourceSafe]
"SCCServerName"="Microsoft Visual SourceSafe"
"SCCServerPath"="D:\\Program Files\\DevStudio\\Vss\\win32\\ssscc.dll"
Microsoft Visual SourceSafe makes the following registry entries:
[HKEY_LOCAL_MACHINE\SOFTWARE\SourceCodeControlProvider]
"ProviderRegKey"="Software\\Microsoft\\SourceSafe"

[HKEY_LOCAL_MACHINE\SOFTWARE\SourceCodeControlProvider\InstalledSCCProviders]
"Microsoft Visual SourceSafe"="Software\\Microsoft\\SourceSafe"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SourceSafe]
"SCCServerName"="Microsoft Visual SourceSafe"
"SCCServerPath"="D:\\Program Files\\DevStudio\\Vss\\win32\\ssscc.dll"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SourceSafe\Databases]
"DevStudio"="D:\\Program Files\\DevStudio\\Vss"
Starbase Versions makes the following registry entries:
[HKEY_LOCAL_MACHINE\SOFTWARE\SourceCodeControlProvider]
"ProviderRegKey"="Software\\StarBase\\MSIntegration"

[HKEY_LOCAL_MACHINE\SOFTWARE\SourceCodeControlProvider\InstalledSCCProviders]
"StarBase Versions"="Software\\StarBase\\MSIntegration"

[HKEY_LOCAL_MACHINE\SOFTWARE\StarBase]

[HKEY_LOCAL_MACHINE\SOFTWARE\StarBase\MSIntegration]
"SCCServerName"="StarBase Versions"
"SCCServerPath"="C:\\WINNT\\System32\\MsSccIntegrationV.dll"

[HKEY_LOCAL_MACHINE\SOFTWARE\StarBase\Versions]

[HKEY_LOCAL_MACHINE\SOFTWARE\StarBase\Versions\2.0]
"Registered User"="Preston L. Bannister"
"Registered Company"="."
"Registered Serial Number"="33-001-200-123456"
"Path"="d:\\Program Files\\Versions\\Versions.exe"
Executing the example cvsscc.regwill make the registry entries:
[HKEY_LOCAL_MACHINE\SOFTWARE\SourceCodeControlProvider]
"ProviderRegKey"="Software\\CVS\\CVS"

[HKEY_LOCAL_MACHINE\SOFTWARE\SourceCodeControlProvider\InstalledSCCProviders]
"Concurrent Versions System"="Software\\CVS\\CVS"

[HKEY_LOCAL_MACHINE\SOFTWARE\CVS]

[HKEY_LOCAL_MACHINE\SOFTWARE\CVS\CVS]
"SCCServerName"="Concurrent Versions System"
"SCCServerPath"="d:\\cyclic\\cvsscc\\dbin\\cvsscc.dll"

Entry points exported from SCC DLL

The following entry points comprise the complete SCC API.

Both Microsoft Visual SourceSafe (ssscc.dll) and Starbase Versions (MsSccIntegrationV.dll) export exactly this set of functions (neither more nor less).

SccAdd
SccAddFromScc
SccCheckin
SccCheckout
SccCloseProject
SccDiff
SccGet
SccGetCommandOptions
SccGetEvents
SccGetProjPath
SccGetVersion
SccHistory
SccInitialize
SccOpenProject
SccPopulateList
SccProperties
SccQueryInfo
SccRemove
SccRename
SccRunScc
SccSetOption
SccUncheckout
SccUninitialize

CVSSCC.DLL

This is the DLL implementing the SCC API. Implements local status operations for efficiency and the avoid the need to load the coworker when simply editing and compiling. Calls the CVSSCC coworker COM interface for operations that actually invoke CVS. The implementation is essentially complete at this point.

CVS_Coworker0.exe

Example implementation of the CVSSCC coworker. Suitable to be merged into your coworker implementation (lots of boilerplate code). CVS_Coworker0 is a minimal COM/ATM application. Use CVS_Coworker0 as a base and you need learn very little about COM or the CVSSCC coworker COM interface.

CVS_Coworker1.exe

Example implementation of the CVSSCC coworker. Suitable to be merged into your coworker implementation (lots of boilerplate code). CVS_Coworker1 is a wizard generated MFC application with COM/ATM support. Use CVS_Coworker1 as a base and you need learn very little about COM or the CVSSCC coworker COM interface.

sccspy.dll

This DLL is used to trace the input and output parameters to third party SCC DLLs. Since the available documentation is limited, likely the best way to understand the SCC API is to see how other source code control packages use the API.

For example, if you compile sccspy.dllwith:

static char* g_sLibraryFilename =
"D:\\Program Files\\DevStudio\\Vss\\win32\\ssscc.dll"   // SourceSafe
//  "C:\\WINNT\\System32\\MsSccIntegrationV.dll"            // Starbase Versions
//  "E:\\Cyclic\\ccvs\\dbin\\cvsscc.dll"                    // CVS
;
You will also want to run sccspy.reg to make sccspy.dll the current SCC provider. You might want to rename the ProviderRegKey value first (though you can recreate the value easily enough). As I switch between sccspy, cvsscc, SourceSafe and Starbase Versions, my registry looks like:
[HKEY_LOCAL_MACHINE\SOFTWARE\SourceCodeControlProvider]
"cvs.ProviderRegKey"="Software\\ZotSoftware\\CVS"
"starbase.ProviderRegKey"="Software\\StarBase\\MSIntegration"
"ProviderRegKey"="Software\\ZotSoftware\\SccSpy"
"ss.ProviderRegKey"="Software\\Microsoft\\SourceSafe"

[HKEY_LOCAL_MACHINE\SOFTWARE\SourceCodeControlProvider\InstalledSCCProviders]
"StarBase Versions"="Software\\StarBase\\MSIntegration"
"Concurrent Versions System"="Software\\ZotSoftware\\CVS"
"Microsoft Visual SourceSafe"="Software\\Microsoft\\SourceSafe"
"SCC API Spy"="Software\\ZotSoftware\\SccSpy"
Only the ProviderRegKeyvalue is looked at by (for example) MSVC to find the source code provider.

When you call an SCC API entry point on sccspy.dll:

  1. Input parameters are logged.
  2. The SourceSafe DLL will be loaded and the same SCC API called.
  3. Output parameters and return code are logged.
The following is the log generated from running the current (minimal) fakecmd.exe linked to sccspy.dll and passing SCC API calls onto SourceSafe.
> SccGetVersion
GetProcAddress(SccGetVersion) returned 481e0b70
SccGetVersion returns 65537
< SccGetVersion
> SccInitialize
pSccHandle : 0x12fd64
sCaller : "fakecmd"
GetProcAddress(SccInitialize) returned 481e0b80
SccInitialize returns 0
*pSccHandle : 0xbe07e8
sSccName : "SourceSafe"
*pSccFeatures 57a0beff USE_OUTPROC HAS_QueryInfo HAS_GetProjPath HAS_AddFromScc +57a0387f
sSccPath : "SourceSafe Database"
*pnCommentLengthCheckout : 63
*pnCommentLengthGeneral : 4095
< SccInitialize
> SccUninitialize
h : 0xbe07e8
GetProcAddress(SccUninitialize) returned 481e0c40
SccUninitialize returns 0
< SccUninitialize

How to test IDE status representation

As an aid for determining how the various IDEs use the SCC file status bits, in the debug build of CVSSCC if a file ends in the extension ".zzz" then the filename is interpreted as a binary number (note only 12 bits are significant). So if you add files to the project in your IDE like:
 
000000000001.xxx  bit 1 is set 
000000000010.xxx  bit 2 is set 
000000000011.xxx  bits 1 and 2 are set 

The following is an Perl script for creating the magic files. Adding the files to your IDE's project is a (tedious) manual operation.
 
                @b4 = (
                "0000",
                "0001",
                "0010",
                "0011",
                "0100",
                "0101",
                "0110",
                "0111",
                "1000",
                "1001",
                "1010",
                "1011",
                "1100",
                "1101",
                "1110",
                "1111"
                );

                @b1 = ("0","1");

                foreach $s1 (@b1) {
                foreach $s2 (@b4) {
                foreach $s3 (@b4) {
                        foreach $s4 (@b4) {
                                open FILE, ">>$s1$s2$s3$s4.zzz"
                                        or die "\nCannot create file!\n";
                                close FILE;
                        }
                }
                print "$s1$s2========.zzz\n";
                }
                }

How to get the SCC API documentation

The SCC API documentation must be obtained from Microsoft, and Microsoft will ask you to sign an NDA (Non-Disclosure Agreement). The method for doing this has changed several times. Originally the way to do this was to send mail to vsource@microsoft.com but this email address is no longer monitored. For a while we had a direct contact at Microsoft, but this was frequently abused (for unrelated purposes), so this was changed to require going through Microsoft Support. Going through Microsoft Support proved ... challenging ... as the humans involved in Support generally didn't have a clue (with some notable exceptions).

The current point of contact (as of July 2000) is:

Visual Source Safe MSSCCI [msscci@microsoft.com]
I have not tried this path, so I can't verify this.

If for any reason the e-mail contact does not work, you may have to revert to the old instructions for going through Microsoft Support. Going through Microsoft Support is a lot less efficient. I was successful in getting routed (eventually) to the right place when I called on 7/21/99, but not without going through a couple humans who were relatively clueless on this subject.

Please try following these instructions before contacting me. I can guarantee you that dozens of people (those that I know of) have successfully obtained the SCC API documentation by following the instructions here.

  1. Call Microsoft Support at (800)936-5800.
  2. Ignore the choices offered and wait to get connected to a live human. No point in telling you which choice is right as it likely will change...
  3. Mention the "Microsoft Common Source Code Control" API and insist on talking to "technical router" or an "engineer" on the SourceSafe team. Odds are no one else will know what you talking about (at least this proved true when I called). You will likely hear suggestions that the information you want is on-line at the Microsoft web site. You will need to insist that it is not. Names that might help: Tom Christian (who did understand what I was asking) and Norm Sooy (in "SourceSafe Development" who was given my request and passed it on to the right person).
This email message details what you will be asked.

Drop me a message if the above instructions don't work for you. Or even if they dowork (I'd like to know...:).

What's New?

1998/07/16 Created.
1998/07/18 Added sccspy.dll and notes about how to use.
Documented SCC API actually used by Microsoft SourceSafe and Starbase Versions (both are the same).
1998/07/19 Posted puzzle #1 (MSDEV stumbles after call the SccQueryInfo).
1998/07/28 Verified parameters to SccInitialize, SccOpenProject and SccQueryInfo appear correct.
Tested with both SourceSafe and Starbase Versions.
1998/08/05 Signed Microsoft NDA to get copy of SCC API documentation.
This means I cannot release source for SCC provider implementation that talks directly to SCC API (not my preference!).
Unfortunately I will have little time to put into this at least through the end of the year.
1998/11/06 Solved puzzle #1 (strncpy is not a good idea if size of destination not known, API is not __stdcall).
Tested skeleton implementations of most SCC entry points.
1998/11/09 Implemented SccQueryInfo and SccPopulateList (local operation only - reads CVS/Entries and checks file modified time).
MSVC FileView in IDE will now show which files are known to CVS and which are modified.
Context menus offer checkout only for missing files, and offer checkin and undo checkout only for modified files.
(Still doesn't do anything with CVS).
1999/01/17 I have not had time to spend on this project lately, and probably will not again have time for at least a month. Roughly 1-2 mails a month come in from people who would like to use CVS/SCC, but so far no one else has time to work on this either. It will get done, but no promises as to when.
1999/03/20 Updated information on how to contact Microsoft to obtain the NDA and the SCC API documentation.
1999/03/24 Updated downloadable files. Fixed a bug in SccOpenProject() and changed the logging behavior to be less confusing (see readme.txt ) in the distribution for more details. Updated contact information for the Microsoft NDA .
1999/04/17 Started on COM interface for CVSSCC coworker. Added checklist to this page. Started final countdown :).
1999/04/18 Finished documentation of COM interface for CVSSCC coworker. Have buildable example implementation of COM interface. Added hack to allow testing use of file status bits via "magic" file extension.
1999/05/02 Working version of CVS_Coworker (an example implementation of the CvsCoworker COM interface) posted. Code was written a week ago, but didn't work as COM wanted either a proxy DLL or the use of only OLE Automation compatible types. Not that the error returned by COM gave any real clue to this...
1999/05/05 Build 10: Updated CVS_Coworker to do more detailed logging by default in the debug version. Fixed (in CVS_Coworker.cpp) a Microsoft bug that caused the command line build of CVS_Coworker to hang. Added VERSIONINFO resources generated by do/build.pl to accurately track binaries and source code controlled build numbers. Bundled coworker sources along with the cvsscc sources.
1999/05/06 Build 16: Worked on the build script do/build.pl (which is why so many builds). More concise and detailed logging of status on refresh. Minor puzzle: Why doesn't MSVC ask for a refresh after modifying a file? Have to request a manual refresh to get icons in file view updated.
1999/05/07 Build 19: Fixed bug in recycled strings in coworker on project re-open. Fixed bug in FindProject when more than one active project. (Thanks to Derek Baum [derek.baum@sbil.co.uk]).
1999/05/11 Build 21: CVS_Coworker.exe now presents a messagebox when either registered or unregistered, so you can tell if it worked. This is only in the debug version, and will be removed once a "real" installation program is used. In addition cvsscc.dll will present a messagebox if connecting to the coworker fails (presumably because the coworker is not registered).
1999/05/24 Build 23: Renamed original example coworker from CVS_Coworker to CVS_Coworker0. Created CVS_Coworker1 based on MFC rather than a minimal ATL skeleton. Interestingly enough, an MFC application when invoked via COM does not present a visible window. This is actually the behavior I wanted, but it is not yet clear how to make the window visible. Time to do some more reading...
1999/06/30 Removed Michelle Khoury as Microsoft contact for NDA information (at her request).
1999/07/22 Removed Scott Regan as the contact for NDA information (at his request). Apparently he is getting a number of messages on unrelated subjects that are consuming his time, and are better answered by Microsoft Support. This is an abuse of his time. Going through Microsoft Support is less efficient, but will have to do.
1999/07/25 Build 27: Added logging to the initial DLL registration. If for some reason "regsvr32 cvsscc.dll" fails, then inspect cvsscc.log for clues (or just send it to me :).
1999/08/04 Build 28: Removed an error from the "coworker" COM interface (one string argument was declared as [in] instead of [in,string] ). Added modified version of WinCVS 1.1b6 to downloads. Removed ccvs.zip (limited webspace) to make room for wincvs.zip file.
1999/08/06 Build 30: Updated the readme.txt file to be up-front about the incomplete implementation. Added GetFilesToAddBufferLength() to the COM interface and getFilesToAddBufferLength() to CvsProject class. Still need to integrate the CVSSCC and WinCVS builds (if possible as the NDA is a problem).
2000/02/06 Added "change of tactics" and pulled downloadables.
2000/07/27 Updated contact information for obtaining SCC API from Microsoft.
2001/05/19 Posted new tactics and ZotezCVS first iteration.

$$ home