Friday, May 7, 2010

Windows Update error 8024402C

Today I decided to check the Windows Update status on my laptop, and to my surprise, I was getting an error code 8024402C. Pressing the “Try again” button didn’t help, I was getting the same error over and over again.

WSUS2

And I clicked the “Get help with this error” link, which indicated a lot of possible causes that lead to this error message. This set me on the right track - while my computer is not “usually connected to a network at work”, I did connect once to the work network and I joined the domain there. (It was more than a month ago, before leaving in vacation, and I didn’t even remembered I did that; it was also the last time updates were installed on the laptop).

And so, when I joined the domain, the domain administrators have set my computer to be managed by Windows Server Update Services (WSUS) , as (not verily clearly) indicated by the message “You receive updates: Managed by your system administrator” near the bottom of the page. (I knew that joining the domain would be bad juju sooner or later, but I had to do it so I can access the TFS servers for source control and bug tracking.)

I started searching for policies that were set on my machine and I came upon this Technet page describing  how to  manage the WSUS automatic updates with Group Policy. Indeed searching in Windows7 for “Group Policy”, launching the policy editor and looking at Computer Configuration/Administrative Templates/Windows Components/ Windows Update I found out I had one policy set, for “Specify intranet Microsoft update service location”

WSUS3 WSUS1

Unfortunately, setting it back to “Not configured” and rebooting the computer, didn’t help.

I then found out the WSUS Client Diagnostics Tool, and when I run it it indicated WSUS was still enabled on my machine, and still using the server name I had cleared out in policies. So the settings must have been preserved somewhere else…  Searching for WSUS configuration settings location I found out a page describing how to use WSUS without Active Directory, and I learned that Windows Update settings are stored in registry under HKLM\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate.

I used RegEdit to change the following registry setting, disabling the use of WSUS server.

[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU]
"UseWUServer"=dword:00000000

I tried again Windows Update and the error code this time changed from 8024402C into 80070057. This stands for ERROR_INVALID_PARAMETER, but indicated I was on the right track.

I stopped and restarted the Windows Update Service (I run in an elevated command prompt these commands)

net stop wuauserv
net start wuauserv

which saved me another reboot, and next time I tried Windows Update things were started working!

I guess next time I’ll connect the laptop to the work network the WSUS server will be re-configured and I’ll have to clear it up again, so here I’m writing this article to remind myself how to do it…

Saturday, March 6, 2010

Network shares on Smb server could not be accessed - again

For a couple of days my server was down due to a hardware failure.  After I fixed the problem and I put the server back online I noticed a problem with the workstations: after login Windows popped up a balloon warning that “Could not reconnect all network drives”

NetworkDrives

All the drives I had mapped to Samba shares on my Infrant ReadyNAS system were now inaccessible, and they were showing disconnected in Windows Explorer.

NetworkDrives2

Double clicking the shares in Windows Explorer was displaying a logon prompt with the following error “The system detected a possible attempt to compromise security. Please ensure that you can contact the server that authenticated you”.

MapError

Typing correct credentials was useless. The dialog just came back. Canceling the dialog was going through 2 more logon prompts and displaying a message listing all personal certificates on the machine. Needless to say, those were certificates for another domain and logon eventually failed.

I deleted the disconnected mapped drives and I was able to recreate them without problems and everything was fine again. Until the first reboot, that is. And then again, network drives were disconnected and “The system detected a possible attempt to compromise security” was back. :-(

Initially I thought Windows may have installed some update in the last week that strengthened the security settings and breaking network shares to old Linux boxes  (It wouldn’t have been the first time). But that wasn’t the case.

I checked access to the domain controller server. It was fine, I could ping it by its Wins name (SOL), by its fully qualified domain name (sol.constantin.comcast.net), by it’s IP address (192.168.0.2), I could access the network shares on the server, etc. So, server being inaccessible didn’t seem to be the problem.

I looked then in the System Event Log to see if any problems were logged. There were lots of errors like these:

  • Time-Service event ID 129: “NtpClient was unable to set a domain peer to use as a time source because of discovery error. NtpClient will try again in 3473457 minutes and double the reattempt interval thereafter. The error was: The entry is not found. (0x800706E1)”
  • GroupPolicy event ID 1129 “The processing of Group Policy failed because of lack of network connectivity to a domain controller. This may be a transient condition. A success message would be generated once the machine gets connected to the domain controller and Group Policy has successfully processed. If you do not see a success message for several hours, then contact your administrator”. with error code 1222 - "The network is not present or not started."
  • Netlogon 5719: “ This computer was not able to set up a secure session with a domain controller in domain CONSTANTIN due to the following: There are currently no logon servers available to service the logon request. This may lead to authentication problems. Make sure that this computer is connected to the network. If the problem persists, please contact your domain administrator.”
I searched the net for more information them, but none of the solutions proposed or diagnostics like this seemed to lead anywhere in my case.

Eventually I rebooted the computer once more, and this time I got two different event types:

  • GroupPolicy event ID 1055: “The processing of Group Policy failed. Windows could not resolve the computer name. This could be caused by one of more of the following:
    a) Name Resolution failure on the current domain controller.
    b) Active Directory Replication Latency (an account created on another domain controller has not replicated to the current domain controller).”

    (and a similar event 1053 for “The processing of Group Policy failed. Windows could not resolve the user name”)

Searching the net for this one proved to be successful. I found this Microsoft support page, which indicated to look for an additional error code in Event Details tab. In my case the error code was 1355 “The specified domain either does not exist or could not be contacted.”. The support page instructed further to “Use nslookup to confirm you can resolve addresses of the domain controllers in the user domain.”

Sure enough, the DNS server was not able to resolve the name of the domain server computer…

Nslookup1

And then it hit me what was wrong. The DNS server I was using was the Wi-Fi router (192.168.0.1), a Netgear/Linux box. This was not able to provide DNS entries correctly for the local network computers, despite them being configured with static addresses. :-( It was my fault, too – I had set the router as preferred DNS when the DC server was down due to the hardware failure…

Solution

So, I went to Control Panel\Network and Sharing Center, clicked on LocalAreaConnection, Properties, selected “Internet Protocol Version 4”, clicked Properties, and switched the Preferred/Alternate DNS Severs to use the domain controller (192.168.0.2) as the Preferred DNS server.

Now I was able to resolve correctly the name of the Domain Controller, and I was able to access the network shares without problem again…

Nslookup2

If you reached this point and you’re asking why I told you all this, it’s because 12 months from now when I may hit again the same problem with the network shares it’s likely I won’t remember it may be due to an innocent switch of the DNS servers. Having it documented in the blog will help me remember. I hope if you searched and reached this article, it might help you too….

Tuesday, March 2, 2010

Implementing disabled WPF toolbar buttons for Visual Studio 2010

 

If you’ve ever wanted to implement a toolbar in WPF you may have come upon this limitation: you can easily set images for the toolbar buttons, but there is no default way of making these images appear grayed when the toolbar buttons are disabled.

To implement the toolbar buttons and menu items, Visual Studio 2010 uses a custom algorithm to create gray images from the original picture. This is publicly available  for consumption via a converter Microsoft.VisualStudio.PlatformUI.GrayscaleImageConverter, implemented in Microsoft.VisualStudio.Shell.10.0 assembly. The converter takes as input an ImageSource and converts to an Image element that uses for source the grayed out version of the image.

If you need to implement toolbars for your package/dialogs you should strongly consider using shell-implemented toolbars (defined by your application via *.vsct files) and used through IVsToolWindowToolbar/IVsToolWindowToolbarHost interfaces. That guarantees a consistent look of all the buttons, separators or split-buttons in your toolbar with the rest of the shell.

For instance, to display a shell-owned toolbar in a WPF dialog you can use IVsUIShell4.CreateToolbarTray() interface to obtain an IVsToolbarTrayHost, then call AddToolbar() on this object to add the toolbar using the guid of your package and the resource Id of the toolbar in vsct, then get the UIElement representing the toolbar using IVsToolbarTrayHost.GetToolbarTray() and position the element to your liking in the dialog.

 

However, there may be situations when you’ll want to implement your own WPF toolbar buttons. To maintain a consistent grayed out look of disabled buttons you may choose to reuse the GrayscaleImageConverter implemented by the shell. Below I describe a way to do this:

1)  Implement a ToolbarButtonImage class having a Source dependency property. You’ll use this to set the button’s image in the “normal” state.

2) The style of the ToolbarButtonImage class will use a trigger to switch the template of the button’s content when the button gets enabled/disabled between a control template (ToolbarButtonImage_Normal) containing the image in the normal state and a control template (ToolbarButtonImage_Disabled) containing the grayed out image produced by the  GrayscaleImageConverter.

3) Add the buttons to the toolbars as follows:

<ToolBar>
    <Button IsEnabled="{Binding ……….}">
       <local:ToolbarButtonImage Source="Resources\ButtonNormalImage.png"/>
    </Button>
</ToolBar>

Below is the sample code for the ToolbarButtonImage and its style:

----------------------------------------------
ToolbarButtonImage.cs
----------------------------------------------

using
System;

using
System.Windows;

using
System.Windows.Controls;

using
System.Windows.Data;

using
System.Windows.Media;

using
System.Windows.Media.Imaging;


namespace
YourApplicationNamespace 
{ 
    public class ToolbarButtonImage : UserControl
 
    { 
        static ToolbarButtonImage()
        {
              DefaultStyleKeyProperty.OverrideMetadata(
typeof(ToolbarButtonImage),

                                new FrameworkPropertyMetadata(typeof(ToolbarButtonImage)));
        } 

        public
static readonly DependencyProperty SourceProperty = DependencyProperty.Register

                               ("Source", typeof(BitmapSource), typeof(ToolbarButtonImage)); 

        public
BitmapSource
Source
        {
            get
            {
                 return (BitmapSource)GetValue(SourceProperty);
            }
            set

            {
                SetValue(SourceProperty,
value);
            }
        }
    }
}

----------------------------------------------
ToolbarButtonImageStyle.xaml
----------------------------------------------

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:YourApplicationNamespace"

    xmlns:ui="clr-namespace:Microsoft.VisualStudio.PlatformUI;assembly=Microsoft.VisualStudio.Shell.10.0">


<ui:GrayscaleImageConverter x:Key="GrayscaleImageConverter"/>


<ControlTemplate x:Key="ToolbarButtonImage_Normal" TargetType="{x:Type local:ToolbarButtonImage}">

     <Image Width="16" Height="16" Source="{TemplateBinding Property=Source}"/>

</ControlTemplate>


<ControlTemplate x:Key="ToolbarButtonImage_Disabled" TargetType="{x:Type local:ToolbarButtonImage}">

     <ContentPresenter Width="16" Height="16" Content="{TemplateBinding Property=Source, Converter={StaticResource GrayscaleImageConverter}}"/>

</ControlTemplate>


<Style x:Key="{x:Type local:ToolbarButtonImage}" TargetType="{x:Type local:ToolbarButtonImage}">
 
    <Setter Property="Template" Value="{StaticResource ToolbarButtonImage_Normal}"/>

    <Style.Triggers>

        <DataTrigger Binding="{Binding IsEnabled, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Button}}}" Value="False">

            <Setter Property="Template" Value="{StaticResource ToolbarButtonImage_Disabled}"/>

        </DataTrigger>

    </Style.Triggers>

</Style>

</ResourceDictionary>

Thursday, February 4, 2010

Drag and drop in Visual Studio 2010

 

Let me explain first how drag and drop works in a WPF application:

1) the Win32 window hosting the WPF controls needs to be registered as a drop target with Windows by calling RegisterDragDrop. When some object is dragged, Windows selects the “closest” Win32 window registered for drag drop under the mouse, and then it calls functions like DragEnter/Drop/etc on the IDropTarget interface provided at registration. WPF does this registration for HwndSource windows, and when an object is dragged over a WPF window, WPF will be called.

2) the WPF control that wants to intercept the drop needs to specify UIElement.AllowDrop=true. When called by Windows, WPF will select the innermost WPF control under the mouse that allows drop and will route to it WPF-style drag and drop events (e.g. PreviewDragEnter events will be tunneled to that control, then DragEnter events will bubble up). The controls and its parents have a chance of intercepting these events.

3) the control or one of the parents needs to recognize one of the formats of the data being dragged, and allow the drop. If no control recognizes the format, the DropEffect will be None and the drop will not be possible.

Now back to Visual Studio.

Visual Studio 2010 and later are WPF applications. The main window and floating windows (toolwindows or documents) are HwndSource, thus are registered for drag and drop by WPF. The shell sets AllowDrop=true on the root WPF elements in these windows, and since this is an inherited property, all child controls (e.g. the toolwindows contents) will automatically allow drop as well.

If the toolwindows host WPF content but they don’t intercept the drag & drop events, the shell will eventually intercept the bubbling WPF events, and will attempt to extract from the dropped data file names to be opened either as solutions/project or in editor windows. Similarly, if the toolwindows host Win32 elements but don’t register them as droptargets with Windows, Windows will pick the shell’s main window as drop target and again the shell will check the dropped data if it contains filenames that can be opened in editor.

A) Drag and drop over Shell-owned elements

The shell owns some elements in the Visual Studio UI, e.g. the frames of the toolwindows and document windows, document tabs in the document well, the main window’s background area, main window’s toolbars, toolbars in toolwindows hosted by the shell, etc., thus it controls dragging and dropping over these elements.

The shell understands only the DataFormat.FileDrop (CF_HDROP) format. This format is used for instance when one or more files are dragged from Windows Explorer. When dropped over Visual Studio’s main window, VS will use the dropped file names to open the files in a Visual Studio editor.

This works when dropping over most shell elements, with a couple of exceptions:
- dropping over tabbed toolwindows tabs or document tabs is disallowed: instead this is used to switch the active toolwindow or document in the tab group.
- dropping over comboboxes in toolbars (if editable, these allow drop with Text format)
- dropping over the main window’s title is not possible (this is a WPF issue)


B) Drag and drop over toolwindows’ content

A tool window implementer has the option of using Win32-based content or using a WPF element as content. When using the VsSDK/MPF classes like ToolWindowPane, the content can be exposed using either the Window or Content properties from the base class.

Win32 content

Whenever a Win32 window is returned from ToolWindowPane.Window, from IVsWindowPane.CreatePaneWindow, or indirectly from IVsUIElementPane.CreateUIElementPane via IVsUIWin32Element, that toolwindow will have a Win32 content. To intercept drop operations on the toolwindow content, the toolwindow’s implementer will need to register the Win32 window with Windows by calling RegisterDragDrop, and providing an IDropTarget, then handling the Windows-style drag and drop calls.

An example of such toolwindow is SolutionExplorer, which registers its content to allow D&D of solution and project items between the projects in the tree.

WPF content

Whenever a FrameworkElement is returned from the ToolWindowPane.Content property, from IVsUIElementPane.CreateUIElementPane (or indirectly via IVsUIWpfElement), the shell will host that toolwindow’s content in a pure-WPF hierarchy, without intervening HWnd. WPF-style events will then flow freely up/down the visual tree starting with the main window (or the floating window root, when the toolwindow is floating).  Conditions 1) and 2) are automatically satisfied, and all you need to do is satisfy 3) – intercept the WPF events for the dropped format you understand. Again, if the toolwindow does not intercept the dropped data and mark the WPF events handled, the shell will intercepts  them and will either deny the drop or will open the files in editors (if the data is in the FileDrop format accepted by the shell).

See the sample below for an example.

C) Drag and drop over toolwindows’ toolbars

To use a shell-implemented toolbars (WPF), a toolwindow can host it in two modes:

a) Letting the shell to host the toolbar. E.g. get an IVsToolWindowToolbarHost from the window frame by calling IVsWindowFrame.GetProperty for VSFPROPID_ToolbarHost, call AddToolbar on the toolbar host. The shell will host the toolbar directly in a WPF tree without intervening hwnds. Any drops over the toolbar will be handled by the shell. To intercept drops over the toolbar area, the toolbar has to be added using a different function: instead of using IVsToolWindowToobar.AddToobar, query the IVsToolWindowToolbarHost2 interface from the toolbar host and call AddToolbar2 method. This allows providing an object implementing IDropTarget interface that will be called by the shell when the drop happens over the toolbar area.

b) Hosting the toolbar yourself. E.g. If your toolwindow content is Win32-based, create a Win32 window child of the toolwindow’s content, and an object implementing IVsToolWindowToolbarHost interface, call  IVsUIShell.SetupToolbar to associate the Win32 child with your toolbar host, then call IVsToolWindowToobar.AddToobar to add the toolbar into the host. This way you can place a toolbar anywhere in your toolwindow’s area. If the toolwindow’s content  is already registered as drop target by calling RegisterDragDrop, Windows will select it as the “closest” drop target under mouse when the drop happens under the toolbar area, too, and you’ll receive the Windows-style calls on the drop target interface. You can also register the toolbar host child window as a separate drop target if you so wish.

------------------------------------------------------------------------------------------------------------------------------

The following sample demonstrates drag and drag of a custom data format, and intercepting the drop in a WPF control. It also demonstrate dragging of data in formats understood by editors and VS shell.

http://www.alinconstantin.net/Download/Example.SimpleDragDropInVS.zip

You need VS2010 and VSSDK2010 installed in order to build the sample and run it under the experimental hive. To view the toolwindow, use the View/OtherWindow/DragAndDropToolwindow command, then drag the labels over the indicated areas.

Capture

Friday, October 23, 2009

A MSSCCI Primer (How Microsoft Source Code Control API works)

I’ve intended to publish this article long time ago, and never found the time to finish all I wanted to wanted to be in it. I’ll publish it now as is, hoping it may still help someone get started…

------------------------

I've been recently asked what's the correct order in which MSSCCI functions should be called for integrating an IDE application like Visual Studio with a MSSCCI (Microsoft Source Code Control) provider.

While looking for references, I realized that the MSSCCI documentation in MSDN is a good reference for the API functions, but it doesn’t do a good job in describing MSSCCI concepts and how to start implementing a MSSCCI-compliant source control provider. It looks like it's time to write such page...

What is a MSSCCI dll?

Basically, a MSSCCI source control provider is a 32-bit Native dynamic link library, exporting a couple of predefined functions with names beginning with “Scc” (e.g. SccAdd, SccCheckout, etc). A MSSCCI provider doesn't need to implement all these functions, but there is a subset of the functions that must be implemented by any provider (more on that later) to make the provider be usable by an Integrated Development Environment (IDE) like Visual Studio.

An IDE loads the MSSCCI dll by calling LoadLibrary or LoadLibraryEx. After that it usually looks up and binds the MSSCCI function by name by calling GetProcAddress, and will start calling the Scc functions directly. When the IDE is done using the MSSCCI provider it can unload the dll by calling FreeLibrary.

There are no Unicode versions of the functions, therefore Unicode-ANSI conversion may need to be performed as necessary by both IDE and the source control provider.

Because the MSSCCI providers are 32 bit dlls, they cannot be loaded directly in 64 bit processes. To the best of my knowledge, there are no plans of creating a 64-bit version of the interface for loading a MSSCCI provider in a 64-bit process. However this limitation can be circumvented by creating a 32-bit COM object that loads and wraps the MSSCCI dll, further exposing COM interfaces functions similar to MSSCCI functions; the COM wrapper object can be co-created in 64-bit processes.

MSSCCI Connections

To perform source control operations with a MSSCCI provider, an IDE needs to open a connection; this is done with the SccOpenProject function. A connection is simply an association (1:1 mapping) between a folder in the source control storage database (project name in MSSCCI terms) and a folder on local disk (local project path). An example (for SourceSafe) might be:

        C:\My Solutions\Wincheat <----> "$/Solutions/Wincheat", CDFAAAA

When the connection is open, the provider can also perform authentication of the user for accessing the source control storage, etc.

Note there are no restriction on the folders mapping. Multiple connections/mappings can be opened from the same local folder pointing to different folders in the scc database; multiple connections can be opened from various local folders pointing to the same project in the scc database; and mapped projects can overlap.

After opening a source control connection, further source control operations are possible using that connection.Within a connection, files are identified only based on their local path; the path must be under the cone defined by the connection local root. The path in storage is automatically deduced based on the connection root folders. Files outside this connection root should not be controllable through this connection.

E.g. The C:\My Solutions\Wincheat\WinCheat.sln can be controlled through the connection above and is associated with $/Solutions/Wincheat/Wincheat.sln. The file C:\My Solutions\OtherSolution\OtherSolution.sln can’t be controlled using this connection, even though in the scc database there may be an matching item at $/Solutions/OtherSolution/OtherSolution.sln.

In the following example, there are 3 connections open

C:\My Solutions\Solution1             <----> "$/Solution1", BCDAAAA
D:\Project1                           <----> "$/Solution1/Project1", KRFAAAA
C:\My Solutions\Solution1\SubProject  <----> "$/Solution1/Project1", KRFAAAA

Depending on which connection is used, the same file in storage $/Solution1/Project1/File.txt can be referenced either as C:\My Solutions\Solution1\Project1\File.txt, D:\Project1\File.txt or C:\My Solutions\Solution1\SubProject\File.txt

A MSSCCI provider implementer should not make assumptions (based on enlistment or other similar mapping information specific to that provider) that a file in the storage is associated with only one file on local disk - at any time a new MSSCCI connection can be opened from any folder on local disk and the same file in storage can be accessed using that connection.

When a connection is no longer needed, the IDE should close it using the SccCloseProject function.

The server path used for opening a connection is specific to each source control provider. An IDE application has no idea of the format (and should not make any assumptions on the format). You may be asking yourself where does the projName string used in SccOpenProject comes from. Usually, during an Open from source control operation the IDE will call SccGetProjPath which allows the user to select a folder in the source control database. The string identifying the selected project is returned to the IDE, and used immediately in new connections, or is persisted in solution/project files and used on subsequent open from disk of that project/solution. Also, the IDE may attempt to retrieve server path strings from mssccprj.scc file if the source control provider creates and maintains such files.

A typical fragment showing opening a connection could look like this:

SccOpenProject(context1, project1, localpath1) open in context1 a connection
project1<---->localpath1
SccCheckin/SccGet/etc invoke source control functions using the connection open by using file paths under localpath1
SccCloseProject(context1) close the connection open in context1

 MSSCCI Contexts

You may have noticed that most of the MSSCCI functions have an argument LPVOID pvContext.

A context is obtained by calling SccInitialize and can be disposed of by calling SccUninitialize.

A context allows identifying the connection that should be used with a specific operation like Get, Checkin, etc, because at one point in time, at most one connection can be opened within a context.

A context is simply a data structure specific to each source control provider; it usually contains information like flags specifying whether a connection is opened or not within that context, information about the connection open, etc.

The typical order of operations with a source control database is:

SccInitialize() receives context
SccOpenProject(context, project, localpath) open in this context a connection
project<---->localpath
SccCheckin(context)/SccGet(context)/etc perform any source control operations using the context and the project<---->localpath connection. The file paths needs to be
SccCloseProject(context) close the connection open in this context
SccUninitialize(context) dispose of context

If an IDE needs to open a different connection to the database:

a) it can reuse an existing context for the new connection, but first it will have to close the currently open connection within that context. Typical order of operations is:

SccInitialize() receives context1
SccOpenProject(context1, project1, localpath1) open in context1 connection
project1<---->localpath1
SccCloseProject(context1) close the connection open in context1
SccOpenProject(context1, project2, localpath2) open in context1 new connection
project2<---->localpath2
SccCloseProject(context1) close the new connection open in context1
SccUninitialize(context1) dispose of context1

b) it can create a new context and open the new connection with that context. For this to work, a provider must support the SCC_CAP_REENTRANT capability to declare it is reentrant, thread-safe and that it supports opening multiple connections. An order of operations may be:

SccInitialize() receives context1
SccOpenProject(context1, project1, localpath1) open in context1 connection
project1<---->localpath1
SccInitialize() receives context2
SccOpenProject(context2, project2, localpath2) open in context1 new connection
project2<---->localpath2
SccCloseProject(context1) close the new connection open in context1
SccCloseProject(context2) close the new connection open in context2
SccUninitialize(context2) dispose of context2
SccUninitialize(context1) dispose of context1

Note that operations on multiple contexts can be interspersed any way you like as long as the order of the operation within a context is the correct one.

Versions, capabilities and extended capabilities

When calling into a MSSCCI provider, an IDE needs to know which source control functionality is supported by the MSSCCI provider (which functions are implemented). There are a couple of functions that return this information.

SccGetVersion is one of the first functions an IDE will call. This returns the version of the MSSCCI provider (currently there can be providers implementing versions 1.0, 1.1, 1.2 or 1.3 of the MSSCCI spec). Certain functions are defined only by higher number versions MSSCCI spec (were introduced later). Thus if a provider reports supporting version 1.1 of the spec, an IDE won’t even bother binding and calling a function like SccWillCreateSccFile introduced in version 1.2 of the spec.

When a MSSCCI provider declares implementing a specific version of a spec, it is not required to implement all the functions defined by that spec version. For instance, a MSSCCI 1.2 provider may implement SccCreateSubProject, but may not support features like batching (SccBeginBatch) or viewing file history (SccHistory).  An IDE will not call a function if the MSSCCI provider does not declare supporting it.

To define the functionality supported, a provider should return the lpSccCaps capabilities flags during the call to SccInitialize(). E.g. Set and return the bit SCC_CAP_HISTORY in the lpSccCaps if your provider supports history operations.

For MSSCCI 1.3 and later providers, additional capabilities flags can be returned by implementing the SccGetExtendedCapabilities() function.

Beside flags specifying which functions are implemented, capabilities flags may specify other information about the provider, e.g. whether comments are supported on certain operations.

Note that an IDE may only use providers implementing specific functionality. E.g. VisualStudio 2002 and later can only use source control providers supporting multiple connections (reentrant providers, with version 1.1 or greater and defining SCC_CAP_REENTRANT flag).

If the provider does not define a capability flag introduced by a later MSSCCI spec version than the version implemented by the provider, the IDE assumes that functionality is not available in the provider, and may fallback to other scc operations. E.g. If a MSSCCI 1.1 provider is used with VS2003 and later, the lack of the SCC_CAP_MULTICHECKOUT capability will make VS attempt other ways of determining whether the provider supports or not multiple checkouts. Or, if a MSSCCI 1.2 provider is used with VS2005 and later to control websites, recursive enumeration of files in the source control database using SccPopulateDirList is not possible and VS will try alternative (and slower) ways of achieving the same result, using SccPopulateList and recursive SccGet operations.

Windows 7 cannot access Smb shares on Infrant ReadyNAS

 

Yesterday I installed Windows 7 upgrading from Vista, which preserved all my settings. Almost. After the first login, Windows 7 popped up balloon warnings that “Could not reconnect all network drives”

NetworkDrives

It turned out that all the drives I had mapped to Samba shares on the Infrant ReadyNAS system and that were working fine in Vista were now inaccessible, and they were showing as disconnected in Windows Explorer.

NetworkDrives2

Double clicking the shares in Windows Explorer, or attempting to access the server by address \\alinc-nas was displaying a logon prompt. Typing the correct password and pressing OK was useless, the logon dialog came back with a “Logon failure: unknown user name or bad password” error.

Logon2 

Attempting to view the shares from command line with “net view” was no better, this one complained “System error 53 has occurred / The network path was not found” or “System error 5 has occurred / Access is denied”

Command

I searched the net and eventually I found the solution. Thanks to Brandon for his article!

The problem can be solved by modifying a security policy, as described below:

- Open the StartMenu and search for “Local Security Policy”. Right click the application icon and choose to RunAsAdministrator. (alternatively you can open the Run dialog and launch “secpol.msc”).

- In the “Local Security Policy” window, expand SecuritySetting/LocalPolicies/SecurityOptions folders in the left pane tree and locate “Network security: LAN Manager authentication level” in the right pane list.

- Double click the line and change its value from the default “Send NTLMv2 response only” into “Send LM & NTLM – use NTLMv2 session security if negotiated”. Click Ok and agree with the warning. You’re done! The shares should now be accessible (there is no need to reboot).

image

image

Wednesday, November 5, 2008

How to migrate from SourceSafe 6.0 to VSS 2005

 

I’ve seen this question asked a couple of times, so I thought it might be time to write a blog entry to have people to point to when I’ll see it again…

Let me start by saying there are no database format changes between VSS6.0 and VSS2005, thus there is no need to convert the database (like it was the case with previous versions). VSS 6.0 can use a database created with VSS 2005, and vice versa (and only VSS2005 will benefit from new features like checkout local version, time zones, etc).

There are two possible migration paths:

a) Want to upgrade from VSS 6.0 to VSS 2005 on the same machine

Since there is no database conversion required, all you need to do is to install VSS 2005. You may install VSS6 and VSS2005 side by side if you want to test the new bits, but should you decide to uninstall VSS6 you will need to repair your VSS2005 installation (or reinstall it).

I recommend uninstalling first VSS 6.0. The uninstall will not delete existing VSS databases on the machine. After that, simply install VSS 2005. If you do it in this order, all the VSS binaries (ssapi.dll, ssscc.dll) will remain registered correctly, and you should be able to just open VSS2005 and have things working as before.

b) Have a machine with VSS 6.0 but want to setup a  new server with VSS2005

Start by setting up the new server machine (install OS, etc.), install IIS if you need to use the database with FrontPage or plan to use VSS remote.

Install VSS2005 on the new machine. VSS2005 does not create a new database on setup, like it was the case with VSS6.0.

A VSS database is comprised by a couple of files on a network share. You will have to copy the VSS databases from the existing machine onto the new machine. Identify the VSS database folders on the old machine. Make sure there are no users still accessing the old database (a good way to do this is to disconnect/remove the network shares on the old machine). Copy the database folder into a new folder on the new machine. Any recursive copy command can be used (xcopy /s, robocopy /mir, WindowsExplorer, etc). On the new machine, share the database folder.

If you’ve been using the VSS database with FrontPage Server Extensions, you’ll need to write a registry key on the new machine. The VSS2005 installer can’t write this key for you like VSS6 did, because it does not create a new database during setup.

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SourceSafe]

“API Current Database”=”Path to the database on the new machine”

Have all other VSS database users uninstall their VSS 6.0 and install VSS2005. While the database can be used in a mixed client environment, it’s recommended that all clients use VSS2005 to benefit of the new features and avoid inconveniences (e.g. VSS6 users won’t be able to merge UTF8 or Unicode files checked in with VSS2005).

Communicate the new database path to all all other team members and have them open the new VSS database by pointing VSS Explorer to the new database.

You may also want now to consider using the new features of VSS 2005. E.g In SSAdmin, Tools/Options/General page consider whether you want to enable CheckoutLocalVersion, set a time zone for the database in the TimeZones tab, use Server/Configure dialog and decide whether you will use this database for remote access or want to configure the LAN service for better performance on LAN, etc.