Ken Felder
Microsoft Corporation
October 1995
The Visual SourceSafe Object Model
Visual SourceSafe Events (the IVSSEvents Interface)
This specification describes the OLE Automation interfaces to Microsoft® Visual SourceSafe™ version 5.0. Future versions of Visual SourceSafe will attempt to make as few changes as possible to these interfaces. Versions earlier than Visual SourceSafe 5.0 do not support these interfaces in any way.
A Microsoft Visual Basic® application can get a Visual SourceSafe object and begin executing commands (such as "Get this file" or "Tell me whether this file is currently checked out"). It can also register itself to receive events from Visual SourceSafe. ("Let me know if someone checks this file out.") The two can be used together: for instance, if you programmatically tell Visual SourceSafe to check a file out, an event is triggered, letting Visual SourceSafe add-ins (and your own) know that the file is about to be checked out. Hence, the following code would cause a system hang by creating an endless loop of events.
Sub BeforeCheckout (File as VSSItem, Local as String)
File.Checkout
End Sub
Avoiding this kind of loop is the responsibility of the user and only requires a little common sense.
Finding a Visual SourceSafe object to drive is similar to finding any other OLE object. A Visual Basic programmer would:
Dim Database as new VSSDatabase
and then call:
Database.Open
A C++ programmer would:
CoCreateInstance
the same object, and once again call the Open method.
The globally unique identifier (GUID) for the Visual SourceSafe database object, found in the file SSAPI.DLL, is 783CD4E2-9D54-11cf-B8EE-00608CC9A71F. You can view the GUID and other information in the .DLL by using the Object Browser in Visual Basic or the utility OLE2VW32.EXE (which comes with Microsoft Visual C++®).
To register for Visual SourceSafe events, add your tool to the user's registry so that Visual SourceSafe can CoCreateInstance your event handling object.
In addition, add yourself to the file SSADDIN.INI. You find this file by looking in the registry under HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SourceSafe\SCCServerPath, which will give the path to a file called SSSCC.DLL. SSADDIN.INI should live in that same directory. Then add a line containing <your ProgID>=1 to this file to register yourself as an add-in.
As an example, suppose that the registry variable were set to C:\VSS\WIN32\SSSCC.DLL. You would want a file called C:\VSS\WIN32\SSADDIN.INI. If that file did not exist, you would create it; if it did exist, you would open it. Then, supposing your programmatic identifier (ProgID) were "CoolAddIn," you would add the line "CoolAddIn=1" to the file. This would tell Visual SourceSafe to load your add-in based on a registry lookup on that ID.
Visual SourceSafe connects to your add-in via the standard connection point interfaces. The following is a brief overview of the system; see the OLE reference manuals for more detail.
A few notes about this process.
A few miscellaneous, but important, remarks:
The Visual SourceSafe object model, as seen in Figure 1, is very simple.
Figure 1. The Visual SourceSafe object model.
VSSDatabase | A Visual SourceSafe database. |
VSSItem | A project or file. Note that there is also a VSSItems, which is a collection for all the children in one project. |
VSSVersion | One way of representing a specific version of a file or project. A VSSVersions is a collection of all the versions of a particular file or project. |
VSSCheckout | A checkout record on a file. Note that once again there is a collection, because one file may have many simultaneous checkouts. |
The VSSDatabase object represents one Visual SourceSafe database, logged in as one user. It supports the IVSSDatabase interface, which contains the methods and properties described below.
This interface is very important because it is the starting point of a Visual SourceSafe session. You always start by calling the Open method to login, and then you get a VSSItem, which is the launching point for all Visual SourceSafe commands.
HRESULT VSSItem ([in]BSTR Spec, [in,defaultvalue(0)]boolean bDeleted, (out,retval)IVSSItem **ppIVSSItem);
HRESULT SrcSafeIni ([out,retval]BSTR *pSrcSafeIni);
HRESULT DatabaseName ([out,retval]BSTR *pDatabaseName);
HRESULT UserName ([out,retval]BSTR *pUsername);
HRESULT CurrentProject ([out,retval]BSTR *pPrj);
HRESULT CurrentProject ([in]BSTR Prj);
HRESULT Open ([in,defaultvalue(0)]BSTR SrcSafeIni, [in,defaultvalue(0)]BSTR Username, [in,defaultvalue(0)]BSTR Password);
This function is how you log into Visual SourceSafe. The first parameter specifies the path and name of a SRCSAFE.INI file to use and is therefore a way of choosing a Visual SourceSafe database. The other parameters specify a user name and password; if you do not specify them, Visual SourceSafe will find the user name from Windows or a user-defined environment variable, if possible. If the user cannot be logged in from this information, the call will fail.
If you do not pass in a SrcSafeIni parameter, Visual SourceSafe will attempt to find the SRCSAFE.INI file itself, using essentially the same algorithm that the Visual SourceSafe Explorer uses. This is a good thing to do if you just want to use whatever Visual SourceSafe database the user tends to work with; however, note that successive calls to Open may wind up in different databases! One safe way to work is to call Open with no SrcSafeIni variable and add your project to Visual SourceSafe, and then get and save the SrcSafeIni property. The next time you want to find that project again, call Open passing in that SrcSafeIni value, and you will be sure of opening the same database.
This object can represent either a file or project in Visual SourceSafe, or an old version of a file or project. It exposes the IVSSItem interface, which is where almost all Visual SourceSafe commands and queries are found. (Old versions are discussed in more detail later, in the section on versions.)
There are two primary ways to get an IVSSItem pointer. One is through a call to IVSSDatabase::VSSItem where you essentially make the very specific request: "give me an IVSSItem pointer for $/My/Web/FU.HTML." The other is through the VSSItems object, which is a collection of all the children of a project: "give me IVSSItem pointers for all the children of $/My/Web."
HRESULT Spec ([out,retval]BSTR *pSpec);
HRESULT LocalSpec ([out,retval]BSTR *pLocal);
HRESULT LocalSpec ([in]BSTR Local);
HRESULT Name ([out,retval]BSTR *pName);
HRESULT Name ([in]BSTR Name);
HRESULT Parent ([out,retval]IVSSItem **ppIParent);
HRESULT Type ([out,retval]int *piType);
HRESULT Deleted ([out,retval]boolean *pbDeleted);
HRESULT Deleted ([in]boolean bDeleted);
HRESULT IsCheckedOut ([out,retval]long *piStatus);
HRESULT IsDifferent ([in,defaultvalue(0)]BSTR Local, [out,retval]boolean *pbDifferent);
HRESULT Binary ([out,retval]boolean *pbBinary);
HRESULT Binary ([in]boolean bBinary);
HRESULT VersionNumber ([out,retval]long *piVersion);
HRESULT Items ([in,defaultvalue(0)]boolean IncludeDeleted, [out,retval]IVSSItems **ppIItems);
HRESULT Checkouts ([out,retval]IVSSCheckouts **ppICheckouts);
Note Many of the methods described here have a parameter called iFlags. The usage of this parameter is described in detail after the list of methods.
HRESULT Add ([in]BSTR Local, [in,defaultvalue(0)]BSTR Comment, [in,defaultvalue(0)]long iFlags, [out,retval]IVSSItem **ppIItem);
HRESULT NewSubproject ([in]BSTR Name, [in,defaultvalue(0)]BSTR Comment, [out,retval]IVSSItem **ppIItem);
HRESULT Destroy ();
Note: This is one of the few methods that can be called validly on a deleted item; whether the item was previously deleted or not, it is gone after this call.
HRESULT Get ([in,out,defaultvalue(0)]BSTR *Local, [in,defaultvalue(0)]long iFlags);
HRESULT Checkout ([in,defaultvalue(0)]BSTR Comment, [in,defaultvalue(0)]BSTR Local, [in,defaultvalue(0)]long iFlags);
HRESULT Checkin ([in,defaultvalue(0)]BSTR Comment, [in,defaultvalue(0)]BSTR Local, [in,defaultvalue(0)] long iFlags);
HRESULT UndoCheckout ([in,defaultvalue(0)]BSTR Local, [in,defaultvalue(0)]long iFlags);
HRESULT Share ([in]IVSSItem *pIItem, [in,defaultvalue(0)]BSTR Comment, [in,defaultvalue(0)]long iFlags);
HRESULT Move ([in]IVSSItem *pINewParent);
HRESULT Label ([in]BSTR Label, [in,defaultvalue(0)]BSTR Comment);
HRESULT Version ([in,optional]VARIANT Version, [out,retval]IVSSItem **ppIItem);
HRESULT Versions ([in, defaultvalue(0)]long iFlags, [out,retval]IVSSVersions **ppIVersions);
RECURS and HISTIGNOREFILES.Each time there is an iFlags parameter, you can pass zero, which means "do all the default things, as specified by the system and/or the user's SS.INI file." The only time you actually pass any of the flags is when you want to explicitly override a particular behavior, to say "do this thing" or "don't do this thing."
As an example, for recursion, you can pass zero, meaning "either recurse or don't, depending on the user's settings." Or, you can pass VSSFLAG_RECURSNO, meaning "do not recurse, no matter what the user's settings are" or VSSFLAG_RECURSYES, meaning "do recurse, no matter what the user's settings are." In general, of course, the default (0) settings should be used unless there is some particular reason to override them.
These flags can be combined by using the Or operator in C++, or simply by adding them in Visual Basic or Visual C++. So you could pass (VSSFLAG_RECURSNO+VSSFLAG_USEROYES), explicitly setting those two settings, but leaving the others to their defaults. Of course, (VSSFLAG_RECURSNO+VSSFLAG_RECURSYES) is invalid.
The actual flags are described below.
VSSFLAG_USEROYES
VSSFLAG_USERONO
Indicate whether the read-only flag should be used and assumed in the user's local director
VSSFLAG_TIMENOW
VSSFLAG_TIMEMOD
VSSFLAG_TIMEUPD
Indicate what date/time stamp Visual SourceSafe should give the local file: the current time (default), the last modification time, or the last check-in time.
VSSFLAG_EOLCR
VSSFLAG_EOLLF
VSSFLAG_EOLCRLF
Indicate what end-of-line character should be used: carriage-return, line-feed, or carriage-return/line-feed.
VSSFLAG_REPREPLACE
VSSFLAG_REPSKIP
VSSFLAG_REPMERGE
VSSFLAG_REPASK
Indicate what to do if a Get would replace an existing writable file on the user's local drive: replace the file, skip the file, or merge into the file. REPASK means that Visual SourceSafe calls your error handling callback function to find out whether it should replace the file or not.
VSSFLAG_CMPFULL
VSSFLAG_CMPCHECKSUM
VSSFLAG_CMPTIME
Indicate how Visual SourceSafe should determine if a file is out of date. When you Get a file, Visual SourceSafe does not physically copy it over if you already have the correct file. By default, a checksum is used for this comparison.
VSSFLAG_RECURSNO
VSSFLAG_RECURSYES
Indicate whether a command should be recursive, that is, whether it should act on an entire project tree.
VSSFLAG_FORCEDIRNO
VSSFLAG_FORCEDIRYES
When Visual SourceSafe recursively gets a project tree, it can put each subproject into its own working directory (FORCEDIRYES), or create a directory tree, ignoring the working directories of subprojects (FORCEDIRNO).
VSSFLAG_KEEPYES
VSSFLAG_KEEPNO
Indicate whether Visual SourceSafe should keep the file checked out after adding or checking it in.
VSSFLAG_DELYES
VSSFLAG_DELNO
VSSFLAG_DELNOREPLACE
Indicate whether the local file should be deleted after an Add, Checkin, or Undocheckout. The third value—replace the local copy with the Visual SourceSafe copy—is valid only on Undocheckout, where it is the default behavior in general.
VSSFLAG_BINBINARY
VSSFLAG_BINTEXT
Indicate whether a file is text or binary. If neither flag is passed, Visual SourceSafe automatically detects the file type at add-time.
VSSFLAG_DELTAYES
VSSFLAG_DELTANO
Indicate whether the file being added to Visual SourceSafe will store old versions of itself (Deltas) or not.
VSSFLAG_UPDUPDATE
VSSFLAG_UPDUNCH
Indicate whether a file being checked in that has not changed at all should be registered as a Checkin (creating a new version), or an Undocheckout. UPDASK means that Visual SourceSafe calls your error handling callback function to find out whether it should check the file in or not.
VSSFLAG_GETYES
VSSFLAG_GETNO
Indicate whether the file should be retrieved (gotten) on commands that do an automatic Get, such as Checkout and Share.
VSSFLAG_CHKEXCLUSIVE
Indicates whether a checkout should be exclusive. If you do not set this flag, the Checkout may be exclusive anyway due to the administrator's setting or the file type. But if you do set this flag, the Checkout will always be exclusive.
VSSFLAG_HISTIGNOREFILES
This flag is used in only one place—when you retrieve the Versions property of a project. The flag corresponds to the Ignore file checkins in the Visual SourceSafe Explorer project History dialog box, but in reverse. That is, if you do not set this flag, the History returns all the events in the life of the project and all its files. If you do set this flag, file histories are not scanned. Thus, you see only events in the life of the project (such as labels, file adds and deletes, and so on), and iterating through all the versions is much faster.
When you want to iterate through all the children (files and subprojects) in a project, you get a VSSItems from that project. The VSSItems object is a collection of all the children of that project. It supports the standard properties and methods of a collection object.
HRESULT Count ([out,retval]long *piCount);
HRESULT Item ([in]VARIANT sItem, [out,retval]IVSSItem **ppIItem);
HRESULT _NewEnum ([out,retval]IUnknown **ppIEnum);
Before diving into the details of the VSSVersion object, it is worthwhile to discuss how versions are treated in general in Visual SourceSafe OLE Automation.
A specific old version of a file is represented by two different objects: a VSSItem and a VSSVersion. These two objects give you different abilities.
This article has primarily discussed VSSItems that represent a file in general (with no reference to version): for instance, $/A/FU.HTML. However, a VSSItem can also be used to represent a specific version of a file: for instance, $/A/FU.HTML version 2. In both cases, the VSSItem gives you general properties of the object (such as its name) and methods (such as Get). So if you call Get on a VSSItem that represents $/A/FU.HTML in general, you get the latest version; but if you call Get on a VSSItem that specifically represents version 2 of that file, you get version 2. You should note that some methods and properties of the IVSSItem interface are not valid when acting on an old version. For instance, if you have a VSSItem that represents version 2 of the file, you cannot set the Deleted property on that object, or call the Checkin method. Such actions are only valid on the file in general, not on a specific version.
The VSSVersion gives you version-specific properties of a specific version, such as the version number and the date/time associated with that change. One of the properties of a VSSVersion is the VSSItem associated with it. So, if you have a VSSVersion that represents version 2 of $/A/FU.HTML and you want to Get that version, you first find a VSSItem from the VSSVersion, and then call the Get method on that VSSItem. Note that you cannot go the other way! That is, there is no way—given a VSSItem that represents an old version—to retrieve a VSSVersion for that version.
As a final note, projects are treated in the exact same way as files. Hence, version 12 of $/A is also represented by both a VSSItem and a VSSVersion object.
Suppose you have a VSSItem that represents the file $/A/FU.HTML in general (not version specific). How do you get objects that represent specific versions? There are two different ways.
The first is the Version property. You retrieve the Version property on your general VSSItem, passing in a version identification string (representing a date, version number, or label), and you receive back a VSSItem representing that particular version of the same file.
The second way is with the Versions property, which returns a VSSVersions collection on the general VSSItem. You iterate through that collection to list all the versions of the file or project. For each version that you receive, you can get properties to display or a VSSItem to act on.
Both of these methods are described in more detail later in this article
When you want to iterate through all the versions of a file or project, you use the Versions property of that file or project to get a VSSVersion object. You use that object to iterate through a series of VSSVersion objects, each of which has enough properties to display version information to the user. Using this object, therefore, you could create a display of the entire history of an object.
However, this object has no methods. If you want to Get an old version, you use the VSSItem property to get a VSSItem that represents that particular version, and then call the Get method on that item.
HRESULT Username ([out,retval]BSTR *pUsername);
HRESULT VersionNumber ([out,retval]long *piVersion);
HRESULT Action ([out,retval]BSTR *pAction);
This is the key variable for understanding what this particular version means. It is also the variable that you would use to recreate the Visual SourceSafe history display in your application. Note, however, that this string does not always give you enough information. When you are enumerating the versions of a project, you may get the string above, "Checked Into $/A". How do you know which file was checked in? The only way to get this information is to use the VSSItem property of the Version object to retrieve a VSSItem that represents that version of that file, and then get the Spec or Name property of the VSSItem to find the file.
HRESULT Date ([out,retval]DATE *pDate);
HRESULT Comment ([out,retval]BSTR *pComment);
HRESULT Label ([out,retval]BSTR *pLabel);
HRESULT VSSItem ([out,retval]IVSSItem **ppIItem);
The VSSVersions object is a collection of all the versions of a given file or project. However, it is a very odd collection object in a number of ways.
The Count property and Item method are not implemented in this collection. The only way to use this collection is to call the _NewEnum method (in C++), or use a for-each loop (in Visual Basic).
You cannot have more than one Versions enumerator open at once. This means that the Clone method is not implemented on the Versions enumerator. More importantly, it means that if you want to get the recursive history of a project, you should allow Visual SourceSafe to do it for you (by using the VSSFLAG_RECURSYES flag on the Versions property when you first get the collection), rather than doing the recursion manually.
There is one further important note: not all the versions that you get are actually versions of the object you started with.
If you are doing a history of $/A/FU.HTML, most of the versions you see will refer to that particular file. However, some of the versions you see will be labels that were applied to the project (not to the file). If you get back the label "2.00b," and then get a VSSItem for that version, you may be getting an item that represents FU.HTML (if the label was applied to the file), or an item that represents $/A (if the label was applied to the project).
Similarly, if you are doing a history of $/A, you will see all the checkins of FU.HTML. So, once again, although you started with one thing (the project), some of your versions refer to a different thing (the file).
So, here is a wrong way to use this interface. You want to find FU.HTML as it was on 10/27/93. You get a Versions collection and work your way through it until the date reaches that point; then you get a VSSItem from that version and call the Get method. You may retrieve exactly what you wanted; or, you may be very surprised to discover that you have retrieved the entire project!
The right way to do that sort of operation is to use the Version method, not the collection. When you ask for the version of FU.HTML with a particular date or label, call Version on FU.HTML, passing in that date or label, and then call Get on that. The Version method, unlike the Versions collection, will always return a version of the item you started with.
HRESULT _NewEnum ([out,retval]IUnknown **ppIEnum);
Returns an enumerator (an IEnumVariant) that supports the standard Next, Skip, and Reset methods (but not Clone, since you can only have one such enumerator open at a time). This method is used explicitly by Visual C++ programmers; Visual Basic programmers do not call it directly, but use the for-each loop, which relies on the enumerator.
Each VSSCheckout on a file represents one checkout record for that file. Hence, if the file is checked out five times, you will iterate through five such records in the VSSCheckouts collection. Each record contains information about that particular checkout in the form of seven properties.
HRESULT Username ([out,retval]BSTR *pUsername);
HRESULT Date ([out,retval]DATE *pDate);
HRESULT LocalSpec ([out,retval]BSTR *pLocal);
HRESULT Machine ([out,retval]BSTR *pMachine);
HRESULT Project ([out,retval]BSTR *pProject);
HRESULT Comment ([out,retval]BSTR *pComment);
HRESULT VersionNumber ([out,retval]long *piVersion);
When you want very basic checkout information for a file, use the IsCheckedOut property. But when you want details, get a VSSCheckouts collection and use it to iterate all the checkouts on that file. You should note that the collection may potentially contain no items (the file is not checked out), one item (the file is checked out), or many items (the file is checked out multiple times), and that merges will automatically be done on check in).
The VSSCheckouts supports the standard properties and methods of a collection object.
HRESULT Count ([out,retval]long *piCount);
HRESULT Item ([in]VARIANT sItem, [out,retval]IVSSCheckout **ppICheckout);
Retrieves one particular checkout record. The item may be specified in one of two ways: either by using an integer (which represents a one-based index into the collection) or by naming a user name (which returns the checkout record, if any, for that particular user).
HRESULT _NewEnum ([out,retval]IUnknown **ppIEnum);
Returns an enumerator (an IEnumVariant) that supports the standard Next, Skip, Reset, and Clone methods. This method is used explicitly by Visual C++ programmers; Visual Basic programmers do not call it directly, but use the for-each loop, which relies on the enumerator.
The section Hooking Up to Receive Visual SourceSafe Events describes the steps you go through to register your add-in with Visual SourceSafe. When the process ends, Visual SourceSafe has found your IVSSEvents interface and is ready to start calling you.
Visual SourceSafe exposes events for a few basic commands to Visual SourceSafe add-ins. All commands described by events are taking place on an individual file, so if a user checks out a project, a separate event will be generated for each file in the project.
The Before event indicates that the user is about to take an action. It is your opportunity to prevent the command from occurring by setting the *pbContinue variable to FALSE (0). As a rule of thumb, you should use the Before event only for the purpose of possibly preventing the command. You should definitely not take any actions that assume the command will occur, because it is possible that another event after you will actually prevent the command.
The After event indicates that the user just took an action. This is when it is appropriate for your program to do things that should be synchronized with the user action.
Note that there is no way for your add-in to tell from where the command is coming. For instance, if you discover that a file is about to be added to Visual SourceSafe, it may be coming from the Visual SourceSafe Explorer, from an integrated development environment (IDE), or even from a Visual SourceSafe add-in using the OLE Automation interface—including your own program! However, it is definitely not coming from the Visual SourceSafe command line because the Visual SourceSafe command line (in version 5.0) does not send events. This unfortunately means that it is possible for a command to happen without your add-in ever getting notified.
HRESULT BeforeAdd ([in]IVSSItem *piPrj, [in]BSTR Local, [out,retval]boolean *pbContinue);
The specified file (Local) is about to be added to the Visual SourceSafe project piPrj.
HRESULT AfterAdd ([in]IVSSItem *pIItem, [in]BSTR Local);
A new file has been added to Visual SourceSafe. *
piItem is a VSSItem pointer for the newly created file.
HRESULT BeforeCheckout ([in]IVSSItem *pIItem, [in] BSTR Local, [out,retval]boolean *pbContinue);
The specified Visual SourceSafe file is about to be checked out to the specified local file name.
HRESULT AfterCheckout ([in]IVSSItem *pIItem, [in] BSTR Local);
The specified Visual SourceSafe file has been checked out to the specified local file name.
HRESULT BeforeCheckin ([in]IVSSItem *pIItem, [in] BSTR Local, [out,retval]boolean *pbContinue);
The specified Visual SourceSafe file is about to be checked in from the specified local file name.
HRESULT AfterCheckin ([in]IVSSItem *pIItem, [in] BSTR Local);
The specified Visual SourceSafe file has been checked in from the specified local file name.
HRESULT BeforeUndoCheckout ([in]IVSSItem *pIItem, [in] BSTR Local, [out,retval]boolean *pbContinue);
The specified Visual SourceSafe file is about to be unchecked out with the specified local file name.
HRESULT AfterUndoCheckout ([in]IVSSItem *pIItem, [in] BSTR Local);
The specified Visual SourceSafe file has been unchecked out with the specified local file name.
HRESULT BeforeRename ([in]IVSSItem *piItem, [in]BSTR NewName, [out,retval]boolean *pbContinue);
The specified file or project (*piItem ) is about to be renamed to the specified new name.
HRESULT AfterRename ([in]IVSSItem *pIItem, [in]BSTR OldName);
The specified file or project (*piItem ) has been renamed from the specified old name.
HRESULT BeforeBranch ([in]IVSSItem *piItem, [out,retval]boolean *pbContinue);
The specified file is about to be branched.
HRESULT AfterBranch ([in]IVSSItem *pIItem);
The specified file has been branched.
HRESULT BeforeEvent ([in]long iEvent, [in]IVSSItem *piItem, [in]BSTR Str, [in]VARIANT var, [out,retval]boolean *pbContinue);
HRESULT AfterEvent ([in]long iEvent, [in]IVSSItem *piItem, [in]BSTR Str, [in]VARIANT var);
These two events are included as part of the interface definition to allow for some expansion in the future without redefining the interface. If future events are added to the IVSSEvents interface, it will be done by calling BeforeEvent and AfterEvent, with the iEvent parameter designating the specific event, *piItem the file or project, and Str and var filling in any additional information required for the particular event. As of the writing of this spec, no iEvent codes are defined and these events are not used.
There are two kinds of errors that can occur during the running of a Visual SourceSafe command: errors and yes/no questions. Because the Visual SourceSafe OLE Automation calls have no user interface component, neither of these can be directly shown to the user. Errors may be returned to the caller as indications that a function call failed. Questions are answered by default; your calling application never even knows the question happened.
When you get an HRESULT back from a Visual SourceSafe method, you can use the standard OLE FAILED macro on that HRESULT to see if it indicates a failure. FAILED will tell you if an error occurred that was so severe that it prevented the method from completing.
The following is a list of all the errors that may be returned by Visual SourceSafe OLE Automation. Please note that your application can call the OLE function GetErrorInfo to get an IErrorInfo pointer and use that standard interface to get more information about any returned errors (such as a string to display to the user and on-line help information to display more details). The strings given here are the U.S. English versions and are listed so that you know the meaning of the errors. If you want to display an error, you should always use GetErrorInfo rather than hard-coding these strings.
Numerical values for these errors are in a file called SSAUTERR.H.
Error Code | English String |
ESS_CORRUPT | File %s may be corrupt. |
ESS_DT_BADDATESTR | Invalid date string: %s |
ESS_DT_INVALID | Invalid time or date string. |
ESS_NOMORE_HANDLES | Too many file handles open. |
ESS_FILE_ACCESSDENIED | Access to file %s denied. |
ESS_FILE_BADDRIVE | Invalid drive: %s |
ESS_FILE_BADHANDLE | Invalid handle. |
ESS_FILE_BADNAME | Invalid file name: %s |
ESS_FILE_BADPARAM | Invalid access code (bad parameter). |
ESS_FILE_BADPATH | Invalid DOS path: %s |
ESS_FILE_CURRENTDIR | Folder %s is in use. |
ESS_FILE_DISKFULL | Disk full. |
ESS_FILE_EXISTS | File %s already exists. |
ESS_FILE_LOCKED | File %s is locked. |
ESS_FILE_NOTFOUND | File %s not found. |
ESS_FILE_READ | Error reading from file. |
ESS_FILE_SHARE | File %s is already open. |
ESS_FILE_TOOMANY | Too many file handles open. |
ESS_FILE_VOLNOTSAME | Cannot rename to another volume. |
ESS_FILE_WRITE | Error writing to file. |
ESS_INI_BADBOOL | Initialization variable %s must be set to Yes or No. |
ESS_INI_BADLINE | Invalid syntax on line %d of file %s. |
ESS_INI_BADNUMBER | Initialization variable %s set to invalid number. |
ESS_INI_BADPATH | Initialization variable %s set to invalid path. |
ESS_INI_BADVALUE | Initialization variable %s set to invalid value. |
ESS_INI_NOSUCHVAR | Cannot find initialization variable %s. |
ESS_INI_NUMRANGE | Initialization variable %s must be between %d and %d |
ESS_INI_TOO_MANY_ENV | Too many SS.INI environment strings. |
ESS_LOCK_TIMEOUT | Timeout locking file: %s |
ESS_MEM_NOMEMORY | Out of memory. |
ESS_NO_TWEAK_CHKDOUT | You cannot modify the properties of a file that is checked out. |
ESS_NOMERGE_BIN_NODELTA | You cannot perform a merge on a binary file or a file that stores latest version only. |
ESS_NOMULTI_BINARY | Cannot check out %s. It is binary and is already checked out. |
ESS_NOMULTI_NODELTA | %s stores only the latest version and is already checked out. |
ESS_OS_NOT_EXE | Error executing: %s |
ESS_SS_ADDPRJASSOCFILE | %s is a Visual SourceSafe configuration file and cannot be added. |
ESS_SS_ADMIN_LOCKOUT | The Visual SourceSafe database has been locked by the Administrator. |
ESS_SS_BADRENAME | Unable to rename %s to %s. |
ESS_SS_CANT_FIND_SSINI | Cannot find SS.INI file for user %s. |
ESS_SS_CHECKED_OUT | File %s is currently checked out by %s. |
ESS_SS_CHECKED_OUT_YOU | You currently have file %s checked out. |
ESS_SS_CHECKOUT_OLD | Cannot check out an old version of a file. |
ESS_SS_CHKOUT_USER | File %s is currently checked out by %s. |
ESS_SS_CONFLICTS | An automatic merge has occurred and there are conflicts. \nEdit %s to resolve them. |
ESS_SS_DEL_ROOT | Cannot delete the root project. |
ESS_SS_DEL_SHARED | A deleted link to %s already exists. |
ESS_SS_FILE_NOTFOUND | File %s not found. |
ESS_SS_HISTOPEN | A history operation is already in progress. |
ESS_SS_INSUFRIGHTS | You do not have access rights to %s. |
ESS_SS_LATERCHKEDOUT | A more recent version is checked out. |
ESS_SS_LOCALRW | A writable copy of %s already exists. |
ESS_SS_MOVE_CHANGENAME | Move does not change the name of a project. |
ESS_SS_MOVE_NOPARENT | Project %s does not exist. |
ESS_SS_MOVE_ROOT | Cannot move the root project. |
ESS_SS_MUST_USE_VERS | Cannot roll back to the most recent version of %s. |
ESS_SS_NOCOMMANCESTOR | Files have no common ancestor. |
ESS_SS_NOCONFLICTS2 | %s has been merged with no conflicts. |
ESS_SS_NODOLLAR | File %s is invalid. Files may not begin with $. |
ESS_SS_NOT_CHKEDOUT | File %s is not checked out. |
ESS_SS_NOT_SHARED | File %s is not shared by any other projects. |
ESS_SS_NOTSEPARATED | Files are not branched. |
ESS_SS_OPEN_LOGGIN | Unable to open user login file %s. |
ESS_SS_PATHTOOLONG | Path %s too long. |
ESS_SS_RENAME_MOVE | Rename does not move an item to another project. |
ESS_SS_RENAME_ROOT | Cannot rename the root project. |
ESS_SS_ROLLBACK_NOTOLD | Cannot rollback to the most recent version of %s. |
ESS_SS_SHARE_ANCESTOR | A project cannot be shared under a descendant. |
ESS_SS_SHARED | File %s is already shared by this project. |
ESS_SSPEC_SYNTAX | Invalid Visual SourceSafe syntax: %s. |
ESS_UM_BAD_CHAR | Bad user name syntax: %s. |
ESS_UM_BAD_PASSWORD | Invalid password. |
ESS_UM_BADVERSION | Incompatible database version. |
ESS_UM_DEL_ADMIN | Cannot delete the Admin user. |
ESS_UM_PERM_DENIED | Permission denied. |
ESS_UM_RENAME_ADMIN | Can not rename the Admin user. |
ESS_UM_TOO_LONG | User name too long. |
ESS_UM_USER_EXISTS | User %s already exists. |
ESS_UM_USER_NOT_FOUND | User %s not found. |
ESS_URL_BADPATH | The URL for project %s was not set properly. |
ESS_VS_CHECKED_OUT | File %s checked out. |
ESS_VS_CHILD_NOT_FOUND | Subproject or file not found. |
ESS_VS_COLLISION | Collision accessing database, please try again. |
ESS_VS_EXCLUSIVE_CHECKED_OUT | File %s is exclusively checked out. |
ESS_VS_ITEMEXISTS | An item with the name %s already exists. |
ESS_VS_LONGNAME | %s is an invalid %s name. |
ESS_VS_MOVE_CYCLE | You can not move a project under itself. |
ESS_VS_NO_DELTA | File %s does not retain old versions of itself. |
ESS_VS_NOT_CHECKED_OUT | File %s cannot be checked into this project. |
ESS_VS_NOT_FOUND | File or project not found. |
ESS_VS_PARENT_NOT_FOUND | Parent not found. |
ESS_VS_VERS_NOT_FOUND | Version not found. |
ESS_VS_WANT_FILE | This command only works on files. |
ESS_VS_WANT_PRJ | This command only works on projects. |
ESS_URL_BUFOVERFLOW | A link in %s was ignored because it was longer than Visual SourceSafe can understand. |
ESS_URL_CANTCHECKHTML | An error occurred while trying to check hyperlinks for %s. |
ESS_SS_ADDINFAILED | Error loading Visual SourceSafe add-in: %s. |
ESS_CANCEL | |
ESS_LOADSTRING_FAILED | Error loading resource string. |
The following questions can occur during the invocation of a Visual SourceSafe method. These questions will be answered automatically as indicated—your application will never know they happened. They are listed here, not because you can do anything about them, but so that you know what to expect when you call Visual SourceSafe.
As an example, consider the following scenario: the user deletes the FU.CPP file in a project, and then attempts to re-add the same file (same name and same contents) to the same project. In the Visual SourceSafe Explorer, when the user attempts to add the file, he will be asked if he wants simply to recover the previously deleted file. When you call the Add method in the Visual SourceSafe OLE Automation, the answer to that question (the first one listed in the table below) is automatically yes; that is, the deleted file is recovered.
Question | Answer |
A deleted copy of this %s file already exists in this project.
Do you want to recover the existing file? |
Yes |
Folder %s not found. Create? | Yes |
Have any conflicts in %s been properly resolved? | Yes |
File %s is currently checked out by %s. Proceed anyway? | Yes |
File %s was checked out to folder %s. Proceed in %s? | Yes |
File %s is checked out to project %s, and you are in %s.
Proceed anyway? |
Yes |
File %s is currently checked out by %s. Delete anyway? | Yes |
You currently have file %s checked out. Delete anyway? | Yes |
An item named %s was already deleted from this project.
Purge the old item and delete this one now? |
Yes |
This version of %s already has a label. Overwrite? | Yes |
The label %s is already used. Remove the old label? | Yes |
%s has been merged with no conflicts. Check in now? | Yes |
Redo the automatic merge? | Yes |
Delete local file: %s? | Yes |
%s is already checked out. Continue? | Yes |
File %s has been destroyed, and cannot be rebuilt. Continue anyway? | Yes |
Project $%s has been destroyed and cannot be rebuilt.
Continue anyway? |
Yes |
$%s was moved out of this project and cannot be rebuilt.
Continue anyway? |
Yes |
%s has changed. Undo check out and lose changes? | Yes |
A deleted file of the same name already exists in this Visual SourceSafe project.
Do you want to recover the deleted file instead of adding your local %s? |
No |
%s is writable. Replace? | No |
%s is checked out. Replace? | No |