You can get creative using a addref/release like approach.  Just create a few functions and an integer variable in your shared datamodule to do the magic, and be sure to call them..partial code follows:
TDMShared = class(tDataModule)
  private
    fQueryCount : integer; // set to 0 in constructor
  public
    function GetQuery : tDataset;
    procedure CloseQuery; 
  end;
function TDMShared.GetQuery : tDataset;
begin
  inc(fQueryCount);
  if fQueryCount = 1 then
    SharedDatsetQry.open;
  Result := shareddatasetqry; // your shared dataset here
end;
procedure TDMShared.CloseQuery;
begin
  dec(fQueryCount);
  if fQueryCount <= 0 then
    shareddatasetqry.close; // close only when no refs left.
end;
EDIT: To do this with multiple queries, you need a container to hold the query references, and a way to manipulate them.  a tList works well for this.  You will need to make appropriate changes for your TDataset descendant, as well as create a FreeAndNil function if you are using an older version of Delphi.  The concept I used for this was to maintain a list of all queries you request and manipulate them by the handle which is in effect the index of the query in the list.  The method FreeUnusedQueries is there to free any objects which no longer have a reference...this can also be done as part of the close query method, but I separated it to handle the cases where a specific query would need to be reopened by another module. 
  Procedure TDMShared.DataModuleCreate(Sender:tObject);
  begin
    dsList := tList.create;
  end;
  Function TDMShared.CreateQuery(aSql:String):integer;
  var
    ds : tAdoDataset;
  begin
    // create your dataset here, for this example using TADODataset
    ds := tAdoDataset.create(nil); // self managed
    ds.connection := database;
    ds.commandtext := aSql;
    ds.tag := 0;
    Result := dsList.add(ds);
  end;
  function TDMShared.GetQuery( handle : integer ) : tDataset;
  begin
    result := nil;
    if handle > dsList.count-1 then exit; 
    if dsList.Items[ handle ] = nil then exit; // handle already closed
    result := tAdoDataset( dsList.items[ handle ]);
    Inc(Result.tag);
    if Result.Tag = 1 then
      Result.Open;    
  end;  
  procedure TDMShared.CloseQuery( handle : integer );
  var
    ds : tAdoDataset;
  begin
    if handle > dsLIst.count-1 then exit;
    ds := tAdoDataset( dsList.items[ handle ]);
    dec(ds.Tag);
    if ds.Tag <= 0 then
      ds.close;
  end;
  procedure TDMShared.FreeUnusedQueries;
  var
    ds : tAdoDataset;
    ix : integer;
  begin
    for ix := 0 to dsList.Count - 1 do
      begin
        ds := tAdoDataset(dsLIst.Items[ ix ]);
        if ds.tag <= 0 then
          FreeAndNil(dsList.Items[ix]);
      end;
  end;
procedure TDMShared.DataModuleDestroy(Sender: TObject);
var
  ix : integer;
begin
  for ix := 0 to dsList.count-1 do
    begin
      if dsLIst.Items[ix] <> nil then
        FreeAndNil(dsLIst.Items[ix]);      
    end;
  dsList.free;  
end;